TypeScript:EventEmitter 子类事件的专用签名

Posted

技术标签:

【中文标题】TypeScript:EventEmitter 子类事件的专用签名【英文标题】:TypeScript: specialized signatures for EventEmitter subclass events 【发布时间】:2016-06-14 14:48:23 【问题描述】:

我有一个基类EventEmitter,它有on 方法来绑定特定事件的处理程序:

class EventEmitter 
    on(event: string, handler: Function) 
        /* add handler internally */
    

    protected emit(event: string, ...args) 
        /* call all handlers listening on event */
    

现在我有各种子类,它们可以发出带有不同参数的不同事件。我想“声明”该特定类可以发出哪些事件:

class MyClass extends EventEmitter 
    on(event: 'event1', handler: (arg1: number) => void): void;
    on(event: 'event2', handler: (arg1: string, arg2: number) => void): void;

所以我的子类可能会发出事件event1event2,但这似乎不是正确的指定方式。 TypeScript (tsc 1.8) 正在更新:

error TS2415: Class 'MyClass' incorrectly extends base class 'EventEmitter'.
  Types of property 'on' are incompatible.
Type '(event: "event1", handler: (arg1: number) => void) => void' is not assignable to type '(event: string, handler: Function) => void'.
  Type '(event: "event1", handler: (arg1: number) => void) => void' provides no match for the signature '(event: string, handler: Function): void'
error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
error TS2391: Function implementation is missing or not immediately following the declaration.

那么,指定我的类可以发出的事件的预期方法是什么?

编辑:我找到了我要查找的名称:Specialized Signatures。但是,它似乎只适用于接口,而不适用于新的 TypeScript 代码。

现在我发现 anothother question 与 2015 年的相同问题,但是那里的解决方案看起来不太正确。那么,今天在 TypeScript 中还有其他方法可以做到吗?

【问题讨论】:

This answer 应该可以帮到你。 【参考方案1】:

指定我的类可以发出的事件的预期方法是什么?

与其使用包含 所有类型的单个 event 流,更容易为 eachevent 流/em> 类型。

这是一个我称之为TypedEvent的概念。一个使用它的示例项目是http://alm.tools/

实施:https://github.com/alm-tools/alm/blob/55a8eb0f8ee411a506572abce92085235658b980/src/common/events.ts#L20-L72

这是一个示例用法:https://github.com/alm-tools/alm/blob/55a8eb0f8ee411a506572abce92085235658b980/src/server/lang/errorsCache.ts#L10

export let errorsUpdated = new TypedEvent<ErrorsUpdate>();
// emit: 
errorsUpdated.emit( /* this will be type checked */);
// consume:
errorsUpdated.on((x)=>null); // x has the correct inferred type

【讨论】:

这可能是一种方法,但它似乎是一种不同的风格。我想调整 node.js (instance.on(eventName, handler)) 和 html DOM (element.addEventListener(eventName, handler)) 的现有样式。 标准的 node.js 风格没有考虑静态类型检查。它依赖于文档而不是代码时间分析,并且不能在 typescript 中很好地建模。 您能否使用我的示例类和事件向我展示您的方法的示例?如果我理解正确,我应该为每个可能的事件定义一个事件子类。我的模块不是外部的,我的类共享相同的命名空间。两个类可能会发出 'event1' / Event1Event 但具有不同的属性,具体取决于发出它的类。

以上是关于TypeScript:EventEmitter 子类事件的专用签名的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:EventEmitter 不是新 MapboxGeocoder 的构造函数

子组件无法通过服务订阅 EventEmitter

如何使用 EventEmitter 将函数传递给子组件?

角度服务中的 EventEmitter 或 RxJS 主题

Angular 5 EventEmitter 无法正常工作

Angular 2,Eventemitter 会触发变化检测吗?