我想使用Immutable的流类型定义来描述地图的形状。
您可以通过以下方式描述对象的形状:
const stateShape: {
id: number,
isActive: boolean
} = {
id: 123,
isActive: true
};
Immutable的地图有类似内容吗?
答案 0 :(得分:29)
不,但是使用记录你可以获得Flow来检查形状而不是类型。
正确的答案是:否,因为地图没有形状 (至少在Flow和Immutable中)。但 Immutable 确实有一个带有形状的“地图”类型。这将是记录。但由于下面描述的原因(因为它并不严格相关),Immutable.Record
的流量libdef非常松散,实际上并不检查形状。
如果我们忽略直接访问Record属性的(可以说是不必要的)功能,我们可以创建一个更好的libdef。看起来像这样:
declare class Record<T: Object> {
static <T: Object>(spec: T, name?: string): Record<T>;
get: <A>(key: $Keys<T>) => A;
set<A>(key: $Keys<T>, value: A): Record<T>;
remove(key: $Keys<T>): Record<T>;
}
通过此声明,我们可以定义记录的形状。 Here it is in action。但是我们仍然无法定义实际值的类型。 Flow确实定义了一个未记录的$PropertyType<T, K>
类型。其中包含对象T
和字符串文字K
。为了使$PropertyType
能够在我们的情况下工作,它需要适用于$Keys<T>
这是一个字符串联合类型。几个星期前,为了实现这一目标,已经开启了一个问题。 It can be found here
在流程中他们是完全不同的。这是一张地图:
type MyMaps = { [key: string]: number }
实际的密钥未知。 Flow知道的唯一事情是所有键必须是字符串,所有值必须是数字。另一方面,对象类型看起来像:
type MyObject = { a: string, x: boolean }
创建或更改newObj
类型的MyObject
对象时,会检查newObj.a
是否为字符串,newObj.x
是否为布尔值。
记录通过直接密钥访问公开每个键/值对。
type R = { a: string }
const r = Record({ a: 'Supa' })
r.a === r.get('a')
这需要r
的类型定义为Record<R>
和R
的交叉(不完全相同,但它足够接近)。所以:
(r: R & Record<R>)
这不起作用,因为Flow缺少对具有对象的交叉类型的支持。 Here's how that looks in action