【问题标题】:Typescript alias generic interfaceTypescript 别名泛型接口
【发布时间】: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&lt;any&gt; 而不是 E

  • 能够定义extendsCustomEvent&lt;any&gt;的具体自定义事件,例如:

    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&lt;any&gt;&gt;并且无法编译:

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&lt;any&gt;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. 为什么我的第一次尝试没有编译?
  2. 为什么我第二次尝试的某些代码无法编译?
  3. 我能比第三种方法做得更好吗?

【问题讨论】:

    标签: typescript class types interface typescript-generics


    【解决方案1】:

    与直觉相反,如果我们使用意义不大的名称,这可能更有意义。

    在第一种情况下,打字稿正在寻找这样的东西:

    export type Handler<T> = (event: T) => void;
    

    我们正在尝试使用CustomEvent&lt;any&gt; 作为类型参数:

    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&lt;any&gt; 不能代替T?我以为T 意味着什么,但事实并非如此;具体来说,它并不意味着泛型类型,对吧?你能链接到一些指定的文档吗? (2) 为什么Typescript认为它是class EventDispatcher定义内的条件类型,而不是Handler定义内的条件类型?
    猜你喜欢
    • 2018-04-09
    • 2019-04-06
    • 1970-01-01
    • 2015-04-01
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多