TypeScript - 从对象中创建联合类型

4

我正在使用 TypeScript 创建一个 EventEmitter,但是我无法找到以下操作的解决方法:

假设我有这样一个接口:

interface EventEmitterSubscription { dispose(): void }

// here it is
interface EventEmitter<T extends { [key: string]: any }> {
  onAnyEvent(callback: (event: { type: ???, payload: ??? }) => void): EventEmitterSubscription
  // ...
}

我找不到一种方法来输入onAnyEvent回调函数,例如对于这样的事件发射器:

EventEmitter<{ onNumberReceived: number, onCatReceived: { cat: ICat }, onPersonNameReceived: string }>

onAnyEvent字段应该是这种类型:

onAnyEvent(callback: (event: { type: 'onNumberReceived', payload: number } | { type: 'onCatReceived', payload: { cat: ICat } } | { type: 'onPersonNameReceived', payload: string }) => void): EventEmitterSubscription

目前我的实现看起来像这样:

onAnyEvent(callback: (event: { type: keyof T, payload: T[keyof T] }) => void): EventEmitterSubscription

除了目前不起作用,例如这将产生类型 onAnyEvent(callback: (event: { type: 'onNumberReceived', payload: number } | { type: 'onNumberReceived', payload: { cat: ICat } } | /* ... */) => void): EventEmitterSubscription

那么我该如何为onAnyEvent字段编写类型呢?

1个回答

7

创建一个联合类型的可能方式是,使用一个映射类型,其中每个属性的类型都是所需联合类型的一个元素,像这样:

type EventTypeMap<T extends { [key: string]: {} }> =
    { [K in keyof T]: { type: K; payload: T[K] } };

然后您可以定义通用联合类型。
type CallbackEventTypes<T extends { [key: string]: {} }> =
     EventTypeMap<T>[keyof EventTypeMap<T>] 

并使用它

interface EventEmitterSubscription { dispose(): void }

interface EventEmitter<T extends { [key: string]: {} }> {
  onAnyEvent(callback: (event: CallbackEventTypes<T>) => void): EventEmitterSubscription
  // ...
}

interface ICat { meow() }

type Emitter = EventEmitter<{ onNumberReceived: number, onCatReceived: { cat: ICat }, onPersonNameReceived: string }>

type HandlerType = Emitter['onAnyEvent'];

// inferred as
//type HandlerType = 
// (callback: (event: { type: "onNumberReceived"; payload: number; }
//                  | { type: "onCatReceived"; payload: { cat: ICat; }; }
//                  | { type: "onPersonNameReceived"; payload: string; }
//            ) => void) => EventEmitterSubscription

这正是我正在寻找的!太棒了! - notrota

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接