我需要一种键入对象的方法,其中键是特定类型的“事件”字段的值,而值是采用相同类型数据子类型的对象的回调数组。
我尝试使用映射类型,但是我是TypeScript的初学者,对此确实很挣扎。
// I have this type structure, where the event is always a string, but the data can be anything (but is constrained by the event)
interface EventTemplate {
event: string;
data: any;
}
export interface CreateEvent extends EventTemplate {
event: 'create_game';
data: {
websocketID: 'string';
};
}
export interface JoinEvent extends EventTemplate {
event: 'join_game';
data: {
gameID: 'string';
};
}
export interface MessageEvent extends EventTemplate {
event: 'message';
data: string;
}
export type WSEvent = CreateEvent | JoinEvent | MessageEvent;
// I want an object like this
type callbacks = {
[key in WSEvent['event']]: ((data: WSEvent['data']) => void)[];
};
// Except that it forces the data structure to match with the key used. IE using a specific WSEvent rather than a generic one
// Something along the lines of:
type callbacks = {
[key in (T extends WSEvent)['event']]: ((data: T['data']) => void)[];
};
// ...only valid..
const callbacks: callbacks = {
// So this should be valid:
message: [(data: MessageEvent['data']): void => {}, (data: MessageEvent['data']): void => {}],
// But this should not be valid, as CreateEvent doesn't have the event 'join_game'
join_game: [(data: CreateEvent['data']): void => {}],
};
如果有帮助,我很高兴对以上任何内容进行重组。
我们本质上需要的是一种通过提供事件名称来查找整个事件类型的方法。这可以使用条件帮助程序类型来完成
type EventByName<E extends WSEvent['event'], T = WSEvent> = T extends {event: E} ? T : never;
第一个通用参数E
必须是事件名称之一。第二个是我们要缩小范围的联合类型。默认为,WSEvent
因此无需指定。然后,条件表达式仅以并集类型返回扩展的那些事件{event: E}
(其中E
是事件名称)。
一旦有了helper类型,就可以很容易地为回调调整现有的映射类型:
type Callbacks = {
[E in WSEvent['event']]: ((data: EventByName<E>['data']) => void)[];
};
有关的名称的旁注callbacks
。建议对类型使用PascalCase。这样可以更轻松地与变量区分开。我已在示例中将其更改为Callbacks
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句