是否可以将流类型包装在不可变容器中?

gf3*_*gf3 14 javascript flowtype immutable.js

例如,给出以下记录:

type UserRecord = {
  id: string;
  name: ?string;
  age: number;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法做相同的以下内容:

/* @flow */

import { List, Map } from 'immutable'

const users: List<Map<UserRecord>> = List();    
let user: Map<UserRecord>;

user = Map({ id: '666', age: 30 });
users.push(user);
Run Code Online (Sandbox Code Playgroud)

否则我最终会简单地使用类似于Map<string, any>我认为将Immutable.js与Flow类型系统一起使用的东西.

vku*_*kin 3

一般来说,这是不可能的,因为记录和地图具有非常不同的语义。映射类型通过键和值的类型进行参数化,因此当您调用时,.get您将获得所有键的相同类型。

不过,有一个解决方法:

declare class Map<T, K1=null, V1=null, K2=null, V2=null> {

  constructor(val: T): void;

  get(key: K1 & $Keys<T>): V1;
  get(key: K2 & $Keys<T>): V2;
  // etc
}

const m: Map<{ foo: string, bar: number }, 'foo', string, 'bar', number> = new Map({
  'foo': 'foo',
  bar: 42
});


m.get('foo') // string
m.get('bar') // number
m.get('baz') // error
Run Code Online (Sandbox Code Playgroud)

使用某种脚本生成此类声明以支持所需数量的键值对可能是个好主意。

这样的声明有点冗长,但是如果你不弄乱类型参数,那么这是安全的。几点评论:

  • 我们使用最近的 Flow 功能,该功能允许我们声明默认类型参数,以便我们可以对任意数量的键值对使用单个声明;

  • K1 & $Keys<T>确保我们只能使用实际类型的键T来检索值;这在某种程度上有助于一致性,不幸的是,我发现没有办法验证值类型的一致性,所以你必须小心这些。