使用 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));
我正在尝试为我的事件侦听器创建类型信息。由于所有事件侦听器都设置在相同的 .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));