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

Posted

技术标签:

【中文标题】在 TypeScript 中使用 Immutable JS 以正确的方式检索 List/Map 的值【英文标题】:Retrieve the value of a List/Map the proper way with Immutable JS in TypeScript 【发布时间】:2021-07-08 20:06:50 【问题描述】:

几个月来我一直在使用 Immutable JS。我真的很喜欢它提供的功能。但是我一遍又一遍地做着我不喜欢的事情。它与从 List 或 Map 中检索值有关。

当检索这个值时,我首先检查它是否存在,当它存在时,我想进一步与它交互。但是直到今天,我仍然不知道如何“正确地”做到这一点。

我知道我正在写的内容可能会更好,因为我已经看到了 fp-ts 等功能框架中的功能(如折叠)。所以我知道必须有更好的方法从 List/Map 中检索值。

有人知道怎么做吗?

我将在下面添加一些代码示例以及指向源代码的链接:

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
  
))

【问题讨论】:

【参考方案1】:

这听起来像unsolved issue of TS。它与 ImmutableJS 没有直接关系,更多的是 TS 中可为空的 getter 函数的一般问题。

您可以通过省略has 检查来重写代码:

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

或者persons.get(id, DEFAULT_PERSON) 可能总是返回一个人对象,但是你必须做if(person === DEFAULT_PERSON) 这比感叹号更难看

或者你禁用 strictNullChecks。

【讨论】:

感谢您的回答,我在 FP 的帮助下找到了更好的方法。我将发布更优雅地处理这种情况的解决方案。【参考方案2】:

我意识到我们已经在函数范式中用 Option 的概念解决了这个问题。我们可以在 Option monad 中插入潜在值,如果有则使用该值,如果没有则安全失败。

我将链接我的代码框,我在 App.tsx 中构建问题,在 App2.tsx 中解决问题。所以有兴趣的可以看看。

【讨论】:

以上是关于在 TypeScript 中使用 Immutable JS 以正确的方式检索 List/Map 的值的主要内容,如果未能解决你的问题,请参考以下文章

使用 typescript-eslint 在 VSCode 编辑器中未显示 Typescript 错误

使用TypeScript中的TypeScript库

深入浅出TypeScript- 在React项目中使用TypeScript

优雅的在vue中使用TypeScript

为啥在 Typescript 泛型中使用 '&'

如何在 Vue (Typescript) 中使用 axios?