例如,给定以下记录:
type UserRecord = {
id: string;
name: ?string;
age: number;
}
是否有某种方法可以执行以下操作:
/* @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);
否则我最终会简单地使用类似 Map<string, any>
的东西我认为这会避免将 Immutable.js 与 Flow 类型系统一起使用。
最佳答案
通常这是不可能的,因为记录和 map 具有非常不同的语义。映射类型使用键和值的类型进行参数化,因此当您调用 .get
时您将获得所有 key 的相同类型。
不过还是有办法的:
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
使用某种脚本生成此类声明以支持所需数量的键值对可能是个好主意。
这样的声明有点冗长,但是如果你不弄乱类型参数的话是安全的。一些评论:
我们使用最新的 Flow 特性,允许我们声明默认类型参数,这样我们就可以对任意数量的键值对使用单个声明;
K1 & $Keys<T>
确保我们只能使用T
类型的实际键检索值;这在某种程度上有助于一致性,不幸的是,我发现没有办法验证值类型的一致性,所以你必须小心这些。
关于javascript - 是否可以将流类型包装在不可变容器中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37952020/