Typescript 别名泛型接口
Posted
技术标签:
【中文标题】Typescript 别名泛型接口【英文标题】:Typescript alias generic interface 【发布时间】:2021-09-16 00:53:16 【问题描述】:我正在尝试将以下代码用于事件调度程序,并更加指定使用的类型(类和接口)。
请注意,我通常有兴趣了解为什么我在此处使用类型/类/接口/泛型类型不起作用,并且对事件本身不太感兴趣。Original code:
type Handler<E> = (event: E) => void;
class EventDispatcher<E>
private handlers: Handler<E>[] = [];
fire(event: E)
for (let h of this.handlers)
h(event);
register(handler: Handler<E>)
this.handlers.push(handler);
我想要达到的目标:
使用 Typescript 的 CustomEvent<any>
而不是 E
。
能够定义extend
sCustomEvent<any>
的具体自定义事件,例如:
export class FormClearedEvent extends CustomEvent<any>
constructor()
super("formCleared");
导出那些特定的自定义事件,连同处理程序和事件分派器
第一次尝试,未编译:
export type Handler<CustomEvent<any>> = (event: CustomEvent<any>) => void; // <-- doesn't compile
// Also, using CustomEvent<any> as the type parameter for the dispacther and its methods, doesn't compile as well.
第二次尝试,让我到处重复SpecificEvent extends CustomEvent<any>>
,并且无法编译:
export type Handler<SpecificEvent extends CustomEvent<any>> = (event: SpecificEvent) => void;
export class EventDispatcher<SpecificEvent extends CustomEvent<any>>
private handlers: Handler<SpecificEvent extends CustomEvent<any>>[] = []; // <-- doesn't compile
fire(event: SpecificEvent extends CustomEvent<any>) // <-- doesn't compile
for (let handler of this.handlers)
handler(event);
register(handler: Handler<SpecificEvent extends CustomEvent<any>>) // <-- doesn't compile
this.handlers.push(handler);
// specific events
export class FormClearedEvent extends CustomEvent<any>
constructor()
super("formCleared");
第三次尝试,成功了,但现在我有两个真正相同的课程(CustomEvent<any>
和 SpecificEvent
):
// specific events
class SpecificEvent extends CustomEvent<any>
export class FormClearedEvent extends CustomEvent<any>
constructor()
super("formCleared");
// SpecificEvent handler
export type Handler<SpecificEvent> = (event: SpecificEvent) => void;
// SpecificEvent dispatcher
export class EventDispatcher<SpecificEvent>
private handlers: Handler<SpecificEvent>[] = [];
fire(event: SpecificEvent)
for (let handler of this.handlers)
handler(event);
register(handler: Handler<SpecificEvent>)
this.handlers.push(handler);
我的问题:
-
为什么我的第一次尝试没有编译?
为什么我第二次尝试的某些代码无法编译?
我能比第三种方法做得更好吗?
【问题讨论】:
【参考方案1】:与直觉相反,如果我们使用意义不大的名称,这可能更有意义。
在第一种情况下,打字稿正在寻找这样的东西:
export type Handler<T> = (event: T) => void;
我们正在尝试使用CustomEvent<any>
作为类型参数:
export type Handler<CustomEvent<any>> = (event: CustomEvent<any>) => void;
-- 这不是一个有效的名称。这就解释了为什么我们的第二次尝试超过了这一点;我们给它一个有效的名字SpecificEvent
,并限制它扩展CustomEvent
:
export type Handler<SpecificEvent extends CustomEvent<any>> = (event: SpecificEvent) => void;
同样,现在我们的类声明中有一个名为 SpecificEvent
的泛型类型:
export class EventDispatcher<SpecificEvent extends CustomEvent<any>>
-- typescript 认为后面的extends
将是条件类型,并期望一个问号。
看起来您可以按照以下方式做一些事情:
export type Handler<E extends CustomEvent> = (event: E) => void;
export class EventDispatcher<E extends CustomEvent>
private handlers: Handler<E>[] = [];
fire(event: E)
for (let handler of this.handlers)
handler(event);
register(handler: Handler<E>)
this.handlers.push(handler);
【讨论】:
(1) 但是为什么CustomEvent<any>
不能代替T
?我以为T
意味着什么,但事实并非如此;具体来说,它并不意味着泛型类型,对吧?你能链接到一些指定的文档吗? (2) 为什么Typescript认为它是class EventDispatcher
定义内的条件类型,而不是Handler
定义内的条件类型?以上是关于Typescript 别名泛型接口的主要内容,如果未能解决你的问题,请参考以下文章