如何从类型映射中推断类型
How to infer type from types map
我不知道如何在 onEvent
函数中确保类型安全。
enum MyEnum {
One,
Two
}
type Payloads = {
[MyEnum.One]: { iAmOne: string; one: number };
[MyEnum.Two]: { iAmTwo: string; two: number };
};
interface BetEvent<ENUM extends MyEnum> {
type: ENUM;
payload: Payloads[ENUM];
}
const onEvent = (ev: BetEvent<any>) => {
if (ev.type === MyEnum.Two) {
ev.type; // should be MyEnum.Two
ev.payload; // should be { iAmTwo: string; two: number };
ev.payload.iAmOne; // should throw Error
}
};
您可以实现 Type Guard 文档enter link description here
但首先你必须声明事件并集:
type Events = BetEvent<MyEnum.One> | BetEvent<MyEnum.Two>;
那我们来声明守卫:
let enumTwoGuard = (ev: Events): ev is BetEvent<MyEnum.Two> => ev.type === MyEnum.Two;
语法ev is BetEvent<MyEnum.Two>
表示TS会在if语句中改变ev
的类型。
完整示例:
const onEvent = (ev: BetEvent<any>) => {
if (enumTwoGuard(ev)) {
ev.type; // BetEvent<MyEnum.Two>.type: MyEnum.Two
ev.payload; // { iAmTwo: string; two: number; }
ev.payload.iAmOne; // ERROR
}
};
给你...
enum BetEventType {
One,
Two
}
type BetPayloads = {
[BetEventType.One]: { iAmOne: string; one: number };
[BetEventType.Two]: { iAmTwo: string; two: number };
};
type BetEvent = {
[T in BetEventType]: {
type: T,
payload: BetPayloads[T]
}
}[BetEventType]
const onEvent = (ev: BetEvent) => {
if (ev.type === BetEventType.Two) {
ev.type; // is BetEventType.Two
ev.payload; // is { iAmTwo: string; two: number };
ev.payload.iAmOne; // gives compile error
}
};
我知道有一个公认的答案,但这个答案无疑更好,因为...
- 无运行时开销(意味着不会在将要执行的已编译代码中添加任何内容)
- 更好的
BetEvent
类型,因为它很好地结合了所有可能的事件类型(悬停鼠标以查看我在说什么)
您应该考虑将其标记为已接受
我不知道如何在 onEvent
函数中确保类型安全。
enum MyEnum {
One,
Two
}
type Payloads = {
[MyEnum.One]: { iAmOne: string; one: number };
[MyEnum.Two]: { iAmTwo: string; two: number };
};
interface BetEvent<ENUM extends MyEnum> {
type: ENUM;
payload: Payloads[ENUM];
}
const onEvent = (ev: BetEvent<any>) => {
if (ev.type === MyEnum.Two) {
ev.type; // should be MyEnum.Two
ev.payload; // should be { iAmTwo: string; two: number };
ev.payload.iAmOne; // should throw Error
}
};
您可以实现 Type Guard 文档enter link description here
但首先你必须声明事件并集:
type Events = BetEvent<MyEnum.One> | BetEvent<MyEnum.Two>;
那我们来声明守卫:
let enumTwoGuard = (ev: Events): ev is BetEvent<MyEnum.Two> => ev.type === MyEnum.Two;
语法ev is BetEvent<MyEnum.Two>
表示TS会在if语句中改变ev
的类型。
完整示例:
const onEvent = (ev: BetEvent<any>) => {
if (enumTwoGuard(ev)) {
ev.type; // BetEvent<MyEnum.Two>.type: MyEnum.Two
ev.payload; // { iAmTwo: string; two: number; }
ev.payload.iAmOne; // ERROR
}
};
给你...
enum BetEventType {
One,
Two
}
type BetPayloads = {
[BetEventType.One]: { iAmOne: string; one: number };
[BetEventType.Two]: { iAmTwo: string; two: number };
};
type BetEvent = {
[T in BetEventType]: {
type: T,
payload: BetPayloads[T]
}
}[BetEventType]
const onEvent = (ev: BetEvent) => {
if (ev.type === BetEventType.Two) {
ev.type; // is BetEventType.Two
ev.payload; // is { iAmTwo: string; two: number };
ev.payload.iAmOne; // gives compile error
}
};
我知道有一个公认的答案,但这个答案无疑更好,因为...
- 无运行时开销(意味着不会在将要执行的已编译代码中添加任何内容)
- 更好的
BetEvent
类型,因为它很好地结合了所有可能的事件类型(悬停鼠标以查看我在说什么)
您应该考虑将其标记为已接受