我正在使用disjoint union types来表示事件,recommended for Redux-like actions也是如此。通常这很好用,但在我的应用程序的某些部分,事件有一个额外的时间戳字段。如何在不重复某事的情况下注释带时间戳的事件的类型?
我尝试使用intersection types合并其他必需属性,但以下操作失败:
/* @flow */
export type EvtA = {type: 'A', prop1: string};
export type EvtB = {type: 'B', prop2: string};
export type Event =
| EvtA
| EvtB;
type Timestamped = { timestamp: number };
type TSEvent = Event & Timestamped;
function show(event : TSEvent) {
console.log(event.timestamp);
// let event = ((e: any): Event);
if (event.type === 'A') {
console.log(event.prop1);
}
}
错误(在http://flow.org/try上):
function show(event : TSEvent) {
^ all branches are incompatible: Either property `prop1` is missing in `EvtB` [1] but exists in `EvtA` [2]. Or property `prop1` is missing in `Timestamped` [3] but exists in `EvtA` [2]. Or property `prop2` is missing in `EvtA` [1] but exists in `EvtB` [4]. Or property `prop2` is missing in `Timestamped` [3] but exists in `EvtB` [4].
References:
12: type TSEvent = Event & Timestamped;
^ [1]
7: | EvtA ^ [2]
12: type TSEvent = Event & Timestamped;
^ [3]
8: | EvtB;
^ [4]
17: console.log(event.prop1);
^ Cannot get `event.prop1` because: Either property `prop1` is missing in `EvtB` [1]. Or property `prop1` is missing in `Timestamped` [2].
References:
12: type TSEvent = Event & Timestamped;
^ [1]
12: type TSEvent = Event & Timestamped;
^ [2]
评论出的类型转换是我目前的hacky解决方法。
(是的,也许更干净的方法可能是type LogEntry = { event: Event, timestamp: number }
,但这需要更改很多其他代码。)
答案 0 :(得分:1)
您可能正在寻找的是物品传播:
(Try)
/* @flow */
export type EvtA = {type: 'A', prop1: string};
export type EvtB = {type: 'B', prop2: string};
export type Event =
| EvtA
| EvtB;
type Timestamped = {timestamp: number };
type TSEventA = {
...EvtA,
...Timestamped,
};
// TSEventA now has type:
// {prop1?: mixed, timestamp?: mixed, type?: mixed}
function show(event : TSEventA) {
console.log(event.timestamp);
// let event = ((e: any): Event);
if (event.type === 'A') {
console.log(event.prop1);
}
}
您可以通过传播exact objects
来保留所有类型信息(Try)
/* @flow */
export type EvtA = {|type: 'A', prop1: string|};
export type EvtB = {|type: 'B', prop2: string|};
export type Event =
| EvtA
| EvtB;
type Timestamped = {|timestamp: number|};
type TSEvent = {
...Event,
...Timestamped
};
// TSEvent now has union type:
// {prop2: string, timestamp: number, type: "B"}
// | {prop1: string, timestamp: number, type: "A"}
function show(event : TSEvent) {
console.log(event.timestamp);
if (event.type === 'A') {
console.log('A', event.prop1);
} else if (event.type === 'B') {
console.log('B', event.prop2);
}
}