Как я могу назначить тип TypeScript для полезных нагрузок событий для класса, такого как EventEmitter? - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть класс, который похож на EventEmitter Node (это может быть даже один и тот же класс).

Как я могу набрать его таким образом, чтобы я мог указать тип обратного вызова для каждого отдельногоимя события?

Например, я бы хотел, чтобы даже "foo" имел полезную нагрузку типа number, а событие "bar" - полезную нагрузку типа string, как в:

const emitter = /* get emitter from somewhere. And how would the type definition look like? */

emitter.on('foo', payload => {
  /* type of payload is number, enforced by TypeScript */
  testNumber('foo') // TS error, 'foo' is not a number
  testNumber(payload) // it works, payload is a number
})

emitter.on('bar', payload => {
  /* type of payload is string, enforced by TypeScript */
  testString(5) // TS error, 5 is not a string
  testString(payload) // it works, payload is a string
})

function testNumber( value: number ) {}
function testString( value: string ) {}

Как бы мы определили объявление EventEmitter, чтобы можно было определить события и их типы, а затем позволить пользователям использовать эти события с правильной проверкой типа?

Может быть, естьспособ определить тип EventEmitter так, чтобы при его создании я передавал аргумент типа, который содержит все ожидаемые типы?

Есть ли способ сделать это динамически после создания?

1 Ответ

0 голосов
/ 29 ноября 2018

Я бы начал с чего-то вроде этого:

interface Events {
  foo: number;
}

interface EventEmitter<T> {
  on<K extends keyof T>(s: K, listener: (v: T[K]) => void);
  emit<K extends keyof T>(s: K, request: T[K]): any;
}

declare const emitter: EventEmitter<Events>;

emitter.on('foo', (payload) => {
  console.log(payload);
});

emitter.emit('foo', 1);

Вот пример на TS Playground .

...