Typescript 从超级调用推断类参数类型
在我使用的项目中,有一个Typescript 从超级调用推断类参数类型,typescript,generics,Typescript,Generics,在我使用的项目中,有一个ClientEvents接口,用于保存事件参数元组类型: interface ClientEvents { ready: []; warn: [reason: string] message: [message: Message]; // ...some more events } 我还有一个EventHandler类,它接受一个类型参数: abstract class EventHandler<E extends keyof ClientEven
ClientEvents
接口,用于保存事件参数元组类型:
interface ClientEvents {
ready: [];
warn: [reason: string]
message: [message: Message];
// ...some more events
}
我还有一个EventHandler
类,它接受一个类型参数:
abstract class EventHandler<E extends keyof ClientEvents> {
protected constructor(public eventName: E) {}
abstract execute(...args: ClientEvents[E]): void;
}
有没有一种方法可以使用
super()
调用的参数推断类参数类型?没有,不容易;推理通常不是这样的。当然,你可以写出来:
class ReadyHandler extends EventHandler<"ready"> {
public constructor() { super('ready'); }
public execute() {}
}
不过,我不确定这是否值得
不,不容易;推理通常不是这样的。当然,你可以写出来:
class ReadyHandler extends EventHandler<"ready"> {
public constructor() { super('ready'); }
public execute() {}
}
不过,我不确定这是否值得
如果您正在创建一个类的实例,则可以从构造函数参数推断泛型类型,但在子类化的情况下,
super
不会发生这种情况。扩展类时,TypeScript需要泛型类型作为类型定义的一部分。我猜,但我认为这可能是因为TypeScript不一定知道在调用super
之前是否需要泛型类型(如果调用正确的话)
您还可以通过使子类泛型并将泛型类型传递给超类来解决这个问题
type EventKeys = keyof ClientEvents;
class ReadyHandler<E extends EventKeys> extends EventHandler<E> {
constructor() {
// cast is necessary or TS will complain since you could technically
// do `new ReadyHandler<'wait'>`.
super('ready' as E);
}
}
type EventKeys=keyof ClientEvents;
类ReadyHandler扩展了EventHandler{
构造函数(){
//强制转换是必要的,否则TS会投诉,因为您可能会
//做“新的预备手”。
super('ready'作为E);
}
}
在这种情况下,E
是从ReadyHandler
的构造函数正确推断出来的,因此您可以调用newreadyHandler()
,而无需指定类型参数
另一个答案中给出了另一种选择,即仅指定类型,如
EventHandler
中所示,这当然需要您编写两次'ready'
。你认为什么更方便取决于你。如果你正在创建一个类的实例,泛型类型可以从构造函数参数中推断出来,但是在子类化的情况下,这不会发生在super
中。扩展类时,TypeScript需要泛型类型作为类型定义的一部分。我猜,但我认为这可能是因为TypeScript不一定知道在调用super
之前是否需要泛型类型(如果调用正确的话)
您还可以通过使子类泛型并将泛型类型传递给超类来解决这个问题
type EventKeys = keyof ClientEvents;
class ReadyHandler<E extends EventKeys> extends EventHandler<E> {
constructor() {
// cast is necessary or TS will complain since you could technically
// do `new ReadyHandler<'wait'>`.
super('ready' as E);
}
}
type EventKeys=keyof ClientEvents;
类ReadyHandler扩展了EventHandler{
构造函数(){
//强制转换是必要的,否则TS会投诉,因为您可能会
//做“新的预备手”。
super('ready'作为E);
}
}
在这种情况下,E
是从ReadyHandler
的构造函数正确推断出来的,因此您可以调用newreadyHandler()
,而无需指定类型参数
另一个答案中给出了另一种选择,即仅指定类型,如
EventHandler
中所示,这当然需要您编写两次'ready'
。您认为什么更方便取决于您。看起来这就是我一直在寻找的解决方案。谢谢看起来这就是我一直在寻找的解决方案。谢谢