Home > database >  How to define a custom event callback function argument shape in a class with typescript?
How to define a custom event callback function argument shape in a class with typescript?

Time:10-24

import EventEmitter from 'events';

type Bar = {
  just: string;
  test: number;
};
class Foo extends EventEmitter {
  constructor() {
    super();
    this.addListener('my_event', (bar: Bar) => {
      console.log(bar);
    });
  }
}

const foo = new Foo();

foo.emit('my_event', {
  /* The question is: */
  /* How to tip the argument key when I enter the `ctrl space` keyboard ? */
});

I don't know how to define the callback argument shape, then the vscode can tip me the event argument key when I enter the ctrl&space keyboard.

CodePudding user response:

See this example:

import EventEmitter from 'events';

type EventMap = {
    foo: string;
    bar: number;
};

class CustomEvents extends EventEmitter {
    constructor() {
        super();
        this.addListener('bar', (bar) => {
            // bar is a number
            console.log(bar);
        });
    }

    addListener<Name extends keyof EventMap>(event: Name, cb: (args: EventMap[Name]) => void) {
        this.addListener(event, cb)
        return this
    }

    emit<Name extends keyof EventMap>(event: Name, payload: EventMap[Name]) {
        this.emit(event, payload)
        return true
    }
}

const foo = new CustomEvents();
foo.addListener('bar', (arg) => {
    arg.toExponential() // ok, because arg is number
})

foo.addListener('bar', (arg: string) => {
    arg.toExponential() // expected error, because arg should be a number
})

foo.emit('bar', 'string') // expected error because payload sjould be a number

enter link description here

you need to create your own methods addListener and emit with appropriate validation. Also, please keep in mind that you need an event map type, where each KEY is an event name and property is an event payload.

You can check my article about typing publish/subscribe pattern

  • Related