简体   繁体   English

在 TypeScript 中使用 Immutable JS 以正确的方式检索 List/Map 的值

[英]Retrieve the value of a List/Map the proper way with Immutable JS in TypeScript

I've been working with Immutable JS for a few months.我已经使用 Immutable JS 几个月了。 And I really like the functionality it gives.我真的很喜欢它提供的功能。 But I've been doing something I don't like over and over again.但是我一遍又一遍地做着我不喜欢的事情。 It has to do with retrieving a value from either a List or Map.它与从 List 或 Map 中检索值有关。

When retrieving this value, I fist check if it even exist, when I it does, I want to interact with it further.在检索这个值时,我首先检查它是否存在,当它存在时,我想进一步与它交互。 But up until this day, I still don't know how to do this "the proper way".但直到今天,我仍然不知道如何做到这一点“正确的方式”。

I know what I'm writing could be much better because I've seen the functionalities (like fold) within a Functional Framework like fp-ts.我知道我正在写的内容可能会更好,因为我已经看到了 fp-ts 等功能框架中的功能(如折叠)。 And so I know there must be a nicer way of retrieving a value from a List/Map.所以我知道必须有更好的方法从 List/Map 中检索值。

Does anyone know how?有谁知道怎么做?

I will add some code examples below and also a link to the source code:我将在下面添加一些代码示例以及指向源代码的链接:

Playground 操场

import { Map, List } from 'immutable'
import { pipe } from 'fp-ts/function'
import { fold } from 'fp-ts/boolean'

// Example 1 - with Map
type Person = {
  name: string
  surname: string
  age: number
}

const persons = Map<number, Person>()
  .set(1, {name: 'Jack', surname: 'Bright', age: 25})
  .set(2, {name: 'Jane', surname: 'Bright', age: 22})
  .set(3, {name: 'Mike', surname: 'Bright', age: 21})

const someProgram = (id: number = 2) => {
  // ... Does some things

  // We need to update a user with id: 2
  if (persons.has(id)) {
    // This is where the problem is. We know that the person exists, because we're in the true clause. But still we get undefined as possible value.
    const person1 = persons.get(id) // Person | undefined

    // Now we add the ! and it works, but this is not nice nor elegant. What is the proper way of doing this (getting an element)?
    const person2 = persons.get(id)! // Person
  } else {
    console.log('Error')
  }
}

// Example 2 - With fp-ts & List
/**
 * I use fp-ts a lot lately, and even with this I get this ugly way of adding the ! at every retrieval.
 * An example with List<Person>. We want to get the first Person in the list if the list isn't empty.
 */
pipe(persons.isEmpty(), fold(
  // onFalse
  () => console.log('Error'),
  // onTrue
  () => {
    // We know that there is a user in this clause. But how do we get it properly?
    const person1 = persons.get(0) // Person | undefined
    const person2 = persons.get(0)! // Person
  }
))

This sounds like a unsolved issue of TS .这听起来像是一个未解决的 TS 问题 It's not directly related to ImmutableJS, more a generic problem with nullable getter functions in TS.它与 ImmutableJS 没有直接关系,更多的是 TS 中可为空的 getter 函数的一般问题。

You could rewrite the code by omitting the has check:您可以通过省略has检查来重写代码:

const person = persons.get(id);
if(person) {
  // do stuff
}

Alternatively persons.get(id, DEFAULT_PERSON) might always return a person object, but then you have to do if(person === DEFAULT_PERSON) which is even uglier than the exclamation mark或者persons.get(id, DEFAULT_PERSON)可能总是返回一个人 object,但是你必须这样做if(person === DEFAULT_PERSON)这比感叹号更难看

Or you disable strictNullChecks.或者您禁用 strictNullChecks。

I've realized that we already solve this problem in the functional paradigm with the concept of Option.我意识到我们已经在函数范式中用 Option 的概念解决了这个问题。 We can insert the potential value in an Option monad and work with the value if there is one, and safely fail when there is none.我们可以在 Option monad 中插入潜在值,如果有则使用该值,如果没有则安全失败。

I'll link my codesandbox, where in App.tsx I construct the problem and in App2.tsx I solve the problem.我将链接我的代码框,我在 App.tsx 中构建问题,在 App2.tsx 中解决问题。 So if you're interested, have a look.所以有兴趣的可以看看。

以“正确的方式”编辑使用不可变的检索数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM