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

Ros*_*mon 4 flowtype immutable.js

使用vanilla JS对象和流强制执行数据结构很容易:

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

const obj: ExampleObjType = {
  key1: 123,
  key2: '123'
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

  • 强制默认值
  • 初始化时无法强制执行无效密钥,仅在访问时执行

理想情况下我可以使用Immutable.Map,像这样:

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

const testMap: TestSpec = Map({
  key1: 123,
  key2: '123',
});
Run Code Online (Sandbox Code Playgroud)

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

有没有办法用Immutable实现我正在寻找的东西?对于真正的类型安全而言,这似乎是一个非常基本的要求,特别是当用于Redux动作有效载荷时.

Gab*_*evi 6

immutable.Record()很难打字.事实上,它是目前输入返回any.一方面,这很不方便,因为您需要TestRecord从头开始描述类型.另一方面,它可以让你随心所欲地输入它!

这是一个选项:

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

const TestRecord: Class<TestSpec> = Record({
  key1: 0,
  key2: '',
});
Run Code Online (Sandbox Code Playgroud)

Class<TestSpec>类型是一类是谁的情况下,有型的类型TestSpec.您不必定义构造函数TestSpec,但通过这样做,Flow将确保obj在它看到时有合适的时间new 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
Run Code Online (Sandbox Code Playgroud)

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

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

在flowtype.org/try上试试这段代码