打字稿别名通用接口

时间:2021-07-05 08:16:50

标签: typescript class types interface typescript-generics

我正在尝试为事件调度程序采用以下代码,并使所使用的类型(类和接口)更加具体。

  • 请注意,我通常有兴趣了解为什么我在这里使用类型/类/接口/泛型类型不起作用,而对事件本身不太感兴趣。

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

  • 能够定义extendCustomEvent<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. 为什么我的第一次尝试无法编译?
  2. 为什么我第二次尝试中的某些代码无法编译?
  3. 我能比第三种方法做得更好吗?

1 个答案:

答案 0 :(得分:0)

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

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

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);
  }
}