【问题标题】:TypeScript - Create Union From ObjectTypeScript - 从对象创建联合
【发布时间】:2018-11-13 07:51:49
【问题描述】:

我正在打字稿中创建一个 EventEmitter,但我无法找到执行以下操作的方法:

假设我有一个这样的界面:

interface EventEmitterSubscription { dispose(): void }

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

我找不到输入 onAnyEvent 回调的方法,例如,对于这样的 eventEmitter:

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 字段呢?

【问题讨论】:

    标签: javascript typescript types


    【解决方案1】:

    创建联合的一种可能方法是使用映射类型,每个属性都具有所需联合的一个元素的类型,如下所示:

    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
    

    【讨论】:

    • 这正是我想要的!太棒了!
    猜你喜欢
    • 1970-01-01
    • 2018-05-05
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    相关资源
    最近更新 更多