我正在嘗試為事件處理程式創建一個型別,以便為事件資料提供自動完成功能。我要處理的事件結構如下:
type MyEvent =
| {
eventA: {
foo: number;
bar: number;
};
}
| {
eventB: {
baz: string;
};
};
到目前為止,這是我為處理程式所擁有的:
type UnionKeys<T> = T extends T ? keyof T : never;
type Handler = {
[K in UnionKeys<MyEvent>]: (data: /* ??? */) => void;
};
const handler: Handler = {
eventA: (data) => console.log(data.foo), // I would like to have working autocomplete for data.* here
eventB: (data) => console.log(data.baz),
};
我不確定如何在 Handler 型別中為“資料”構造一個型別以匹配事件。有任何想法嗎?
uj5u.com熱心網友回復:
如果您想堅持使用 的確切結構MyEvent,請考慮以下示例:
type UnionKeys<T> = T extends T ? keyof T : never;
// credits goes to https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties#answer-65805753
type StrictUnionHelper<T, TAll> =
T extends any
? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>
type MyEvent = StrictUnion<
| {
eventA: {
foo: number;
bar: number;
};
}
| {
eventB: {
baz: string;
};
}>;
type Handler = {
[K in keyof MyEvent]: (data: NonNullable<MyEvent[K]>) => void;
};
const handler: Handler = {
eventA: (data) => {
data.bar // ok
data.foo // ok
},
eventB: (data) => {
data.baz // ok
}
};
操場
但是,我不喜歡我被迫使用NonNullable. 這似乎是一個黑客。可以在分布式條件型別的幫助下獲取所有密鑰:
type MyEvent =
| {
eventA: {
foo: number;
bar: number;
};
}
| {
eventB: {
baz: string;
};
};
type Keys<T> = T extends Record<infer Key, infer _> ? Key : never;
type Values<T> = T[keyof T]
type Handler = {
[K in Keys<MyEvent>]: (data: Values<Extract<MyEvent, Record<K, unknown>>>) => void;
};
const handler: Handler = {
eventA: (data) => {
data.bar // ok
data.foo // ok
},
eventB: (data) => {
data.baz // ok
}
};
操場
請記住,有一種更簡單的方法。我認為值得創建映射資料結構,就像這里:
type MyEvent = {
eventA: {
foo: number;
bar: number;
},
eventB: {
baz: string;
}
}
type Handler = {
[K in keyof MyEvent]: (data: MyEvent[K]) => void;
};
const handler: Handler = {
eventA: (data) => {
data.bar // ok
data.foo // ok
},
eventB: (data) => {
data.baz // ok
}
};
你可能在這個有興趣例子也
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/403098.html
標籤:
