在 TypeScript 中使用 Immutable JS 以正确的方式检索 List/Map 的值
Retrieve the value of a List/Map the proper way with Immutable JS in TypeScript
我已经使用 Immutable JS 几个月了。我真的很喜欢它提供的功能。但是我一直在一遍又一遍地做我不喜欢的事情。它与从 List 或 Map 中检索值有关。
当检索这个值时,我首先检查它是否存在,当我存在时,我想与它进一步交互。但直到今天,我仍然不知道如何“正确地”做到这一点。
我知道我正在写的东西可能会更好,因为我已经看到像 fp-ts 这样的功能框架中的功能(如折叠)。所以我知道必须有更好的方法从 List/Map.
中检索值
有人知道怎么做吗?
我将在下面添加一些代码示例,并在源代码中添加一个link:
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
}
))
这听起来像 unsolved issue of TS。它与 ImmutableJS 没有直接关系,更多的是 TS 中可空 getter 函数的一般问题。
您可以通过省略 has
检查重写代码:
const person = persons.get(id);
if(person) {
// do stuff
}
或者 persons.get(id, DEFAULT_PERSON)
可能总是 return 一个人对象,但是你必须做 if(person === DEFAULT_PERSON)
这比感叹号
更难看
或者您禁用 strictNullChecks。
我意识到我们已经通过 Option 的概念在函数范式中解决了这个问题。我们可以在 Option monad 中插入潜在值,如果存在则使用该值,并在存在 none.
时安全地失败
我会 link 我的 codesandbox,在 App.tsx 中我构建问题,在 App2.tsx 中我解决问题。有兴趣的可以看看
我已经使用 Immutable JS 几个月了。我真的很喜欢它提供的功能。但是我一直在一遍又一遍地做我不喜欢的事情。它与从 List 或 Map 中检索值有关。
当检索这个值时,我首先检查它是否存在,当我存在时,我想与它进一步交互。但直到今天,我仍然不知道如何“正确地”做到这一点。
我知道我正在写的东西可能会更好,因为我已经看到像 fp-ts 这样的功能框架中的功能(如折叠)。所以我知道必须有更好的方法从 List/Map.
中检索值有人知道怎么做吗?
我将在下面添加一些代码示例,并在源代码中添加一个link:
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
}
))
这听起来像 unsolved issue of TS。它与 ImmutableJS 没有直接关系,更多的是 TS 中可空 getter 函数的一般问题。
您可以通过省略 has
检查重写代码:
const person = persons.get(id);
if(person) {
// do stuff
}
或者 persons.get(id, DEFAULT_PERSON)
可能总是 return 一个人对象,但是你必须做 if(person === DEFAULT_PERSON)
这比感叹号
或者您禁用 strictNullChecks。
我意识到我们已经通过 Option 的概念在函数范式中解决了这个问题。我们可以在 Option monad 中插入潜在值,如果存在则使用该值,并在存在 none.
时安全地失败我会 link 我的 codesandbox,在 App.tsx 中我构建问题,在 App2.tsx 中我解决问题。有兴趣的可以看看