使用TypeScript和EventEmitter键入事件

Kur*_*ton 3 generics eventemitter typescript

我正在尝试使用TypeScript将强类型事件添加到类似EventEmitter的系统中.

目前,我们定义了以下类型:

interface TypedMsg<Name, T> {
  messageType: Name;
  message: T;
}

type TypedMsgFoo = TypedMsg<'FOO', string>;
type TypedMsgBar = TypedMsg<'BAR', number>;
type EitherFooOrBar = TypedMsgFoo | TypedMsgBar;
Run Code Online (Sandbox Code Playgroud)

我想定义一个界面,如:

interface EventHandler<T extends TypedMsg<any, any> {
  on: (messageType: T.messageType, handler: (T.message) => void) => void;
}
Run Code Online (Sandbox Code Playgroud)

但是Typescript不支持提取类似的子类型T.messageType.还有另一种方法吗?

最终目标是通过以下方式定义具有正确输入的处理程序:

class FooBarHandler implements EventHandler<EitherFooOrBar> {
  on(messageType: EitherFooOrBar.messageType) {...}
}
Run Code Online (Sandbox Code Playgroud)

art*_*tem 5

Typescript确实支持提取成员类型,只是语法有点不寻常 - 它被称为索引访问类型操作符

interface TypedMsg<Name, T> {
  messageType: Name;
  message: T;
}

type TypedMsgFoo = TypedMsg<'FOO', string>;
type TypedMsgBar = TypedMsg<'BAR', number>;
type EitherFooOrBar = TypedMsgFoo | TypedMsgBar;

interface EventHandler<T extends TypedMsg<{}, {}>> {
  on: (messageType: T['messageType'], handler: (m: T['message']) => void) => void;
}

class FooBarHandler implements EventHandler<EitherFooOrBar> {
    on(
        messageType: EitherFooOrBar['messageType'], 
        handler: (m: EitherFooOrBar['message']) => void
    ) {

    }
}
Run Code Online (Sandbox Code Playgroud)

然而,用明确拼写出来的类型键入所有这些声明很快就会变得非常繁琐 - 你会想要设计一些允许打字稿为你推断类型的东西,例如类似这样的问题:TypeScript类型推理/缩小挑战