更简单的方法来强制执行类型化的不可变数据结构?

时间:2016-08-09 20:24:42

标签: immutable.js flowtype

使用vanilla JS对象和流程实施数据结构很简单:

type ExampleObjType = {
  key1: number,
  key2: string
};

const obj: ExampleObjType = {
  key1: 123,
  key2: '123'
};

这似乎需要一个不必要的大量样板来在Immutable中强制执行类似的结构:

type TestSpec = {
  key1: number,
  key2: string,
};

const TestRecord = Record({
  key1: 0,
  key2: '',
});

const record: TestSpec & Record<TestSpec> = new TestRecord({
  key1: 123,
  key2: '123',
});

此外,上述结构有一些主要缺点:

  • 强制默认值
  • 初始化时无效处理无效密钥,仅限访问

理想情况下,我可以使用Immutable.Map,如下所示:

type TestSpec = Map<{key1: number, key2: number}>;

const testMap: TestSpec = Map({
  key1: 123,
  key2: '123',
});

但是,当前实现只允许键入键和值类型。我可以使用类似type Key = 'key1' | 'key2'之类的东西约束键类型,但是我仍然不会明确键入每个键的值。

有没有办法用Immutable完成我正在寻找的东西?这似乎是真正的类型安全的基本要求,特别是当用于Redux动作有效载荷时。

1 个答案:

答案 0 :(得分:6)

immutable.Record()很难输入。实际上,it's currently typed要返回any。一方面,这很不方便,因为您需要从头开始描述TestRecord的类型。另一方面,它可以让你随心所欲地输入它!

这是一个选项:

interface TestSpec {
  constructor(defaults: $Shape<TestSpec>): void,
  key1: number,
  key2: string,
};

const TestRecord: Class<TestSpec> = Record({
  key1: 0,
  key2: '',
});

Class<TestSpec>类型是实例具有类型TestSpec的类的类型。您不必在TestSpec中定义构造函数,但通过这样做,Flow会确保objnew TestRecord(obj)看到正确的时间。

(注意:$Shape<TestSpec>是一个对象的类型,可能有也可能没有。所以在这种情况下它基本上意味着{key1?: number, key2?: string}

new TestRecord({key1: 123,  key2: '123'}); // OK
new TestRecord({key1: 123}); // OK
new TestRecord({key2: '123'}); // OK

new TestRecord({key2: 123}); // Error number -> string
new TestRecord({key1: '123'}); // Error string -> number
new TestRecord({key1: 123,  key2: '123', key3: 'blah'}); // Error unknown property key3

Flow将检查实例属性是否具有正确的类型

const record = new TestRecord({key1: 123,  key2: '123'});
(record.key1: string); // Error number -> string
(record.key2: number); // Error string -> number

Try this code on flowtype.org/try

相关问题