在 Node.js 中使用 EventEmitter 和 Typescript 的类型安全侦听器

rev*_*evy 5 javascript node.js eventemitter typescript

给定一个Typescript接口和一个扩展Node.js EventEmitter 的类,是否可以定义自定义侦听器来对函数参数进行类型安全检查?

给出以下示例:

import { EventEmitter } from 'events';

interface Payload {
    id: string;
    weight: number;
}

class CustomEventEmitter extends EventEmitter {
    constructor() {
        super();

        this.on('my_event', (data) => {
            // I would like data to be implicitly inferred as Payload type
            console.log(data.weight); // This should compile
            console.log(data.something); // This should not compile
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

节点 EventEmitter 侦听器定义为(...args: any[]) => void),我想重写该any[]类型并使用自定义定义的类型。是否可以?

Cha*_*nce 12

是的,有一个很棒的包叫做Typed-Emitter (项目链接),它对我来说非常有效。

\n

来自他们的文档:

\n
import {EventEmitter} from "events" // I made a slight change here as I\'ve needed to explicitly import EventEmitter from events\nimport TypedEmitter from "typed-emitter"\n\n// Define your emitter\'s types like that:\n// Key: Event name; Value: Listener function signature\ninterface MessageEvents {\n  error: (error: Error) => void,\n  message: (body: string, from: string) => void\n}\n\nconst messageEmitter = new EventEmitter() as TypedEmitter<MessageEvents>\n\n// Good \nmessageEmitter.emit("message", "Hi there!", "no-reply@test.com")\n\n// TypeScript will catch those mistakes \xe2\x9c\x8b\nmessageEmitter.emit("mail", "Hi there!", "no-reply@test.com")\nmessageEmitter.emit("message", "Hi there!", true)\n\n// Good \nmessageEmitter.on("error", (error: Error) => { /* ... */ })\n\n// TypeScript will catch those mistakes \xe2\x9c\x8b\nmessageEmitter.on("error", (error: string) => { /* ... */ })\nmessageEmitter.on("failure", (error: Error) => { /* ... */ })\n
Run Code Online (Sandbox Code Playgroud)\n
class MyEventEmitter extends (EventEmitter as new () => TypedEmitter<MyEvents>) {\n  // ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

对于您的示例,这应该有效:

\n
\nimport { EventEmitter } from \'events\';\nimport TypedEmitter from "typed-emitter"\n\ninterface Payload {\n    id: string;\n    weight: number;\n}\n\ninterface CustomEventEmitterEvents {\n  my_event: (data: Payload) => void\n}\n\nclass CustomEventEmitter extends (EventEmitter as new () => TypedEmitter<CustomEventEmitterEvents>) {\n    constructor() {\n        super();\n\n        this.on(\'my_event\', (data) => {\n            // I would like data to be implicitly inferred as Payload type\n            console.log(data.weight); // This should compile\n            console.log(data.something); // This should not compile\n        });\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n