使用 TypeScript 泛型作为索引

Using TypeScript generics as index

我正在尝试为我的事件侦听器创建类型信息。由于所有事件侦听器都设置在相同的 .on() 函数上,因此我使用的是泛型。

type Name = "error" | "connected";

type Callback = {
    error: (err: Error) => void,
    connected: (err: number) => void,
};

function on<T extends Name>(eventName: T, callback: Callback[T]): void { }

on("error", (err) => err.stack);
on("connected", (err) => err.stack);

当我尝试将 number 用作 Error 时,我希望上面的 connected 事件给我一个错误,但是我根本没有得到任何类型提示对于我的回调函数。

但是,如果 Callback 中的所有函数定义都匹配,它就会开始工作。如下:

type Callback = {
    error: (err: Error) => void,
    connected: (err: Error) => void,
};

我在 VS 代码中的意思的 GIF:

我是不是做错了什么?

看来你在做工程方面的事情。

事件可以在一些枚举中列出。

enum EVENTS{
  ERROR = "ERROR",
  CONNECTED = "CONNECTED"
}

on 方法不能泛型

function on(eventName: EVENTS, callback: (v: any) => void): void { }

还有几个例子

on(EVENTS.ERROR, (v: any) => {
  if(v instanceof Error){
    console.log(v.stack);
  }
});

on(EVENTS.CONNECTED, (v:any) => {
  console.log(v);
});

通常很难设置事件值的类型。

对不起。这里是编辑函数。

function on<T>(eventName: EVENTS, callback: (v: T) => void): void { }

on<Error>(EVENTS.ERROR, (err) => {  
    console.log(err.stack);  
});

on<any>(EVENTS.CONNECTED, (v) => {
  console.log(v);
});

这似乎是代表编译器中的推理引擎的一种奇怪行为。

原因推测:如果输入第二个参数,如Callback[T],引擎将尝试根据参数类型确定T。所以如果你没有明确指定箭头函数的类型,推理引擎会推断箭头函数的参数为​​ any 并尝试根据箭头函数类型猜测 T 。 (如果你 运行 with strict 你实际上会收到一个错误,指出参数隐含类型为 any)。

有两种可能的解决方案:

使用双函数方法,其中 T 在第一次调用中确定,并在传递参数的第二次调用中已知:

type Callback = {
    error: (e: Error) => void
    connected: (e: string) => void
};
function on<T extends Name>(eventName: T) { 
    return function(callback: Callback[T])
    {
    };
}

on("error")(e=> e.stack);
on("connected")(e=> e.substr(1));

如果函数之间唯一不同的是参数类型,并且您使用的是 2.8 或更早版本(在撰写本文时尚未发布,但它在 RC 中,您可以通过 npm install -g typescript@rc 获得)您可以只获取不同的参数,推理引擎不会尝试使用第二个参数来推断 T

type Arg0<T> =  T extends (p1: infer U) => any ? U: never;
function on<T extends keyof Callback>(eventName: T, callback: (e: Arg0<Callback[T]>) => void) : void { }

on("error", e=> e.stack);
on("connected", e=> e.substr(1));