Hur kan jag tilldela en TypeScript-typ för händelsedata för en klass som EventEmitter?
Jag har en klass som är precis som Nodes EventEmitter (det kan till och med vara samma klass).
Hur skriver jag det på ett sätt så att jag kan specificera vilken callback-typ som gäller för varje olika händelsenamn?
Till exempel skulle jag vilja att även "foo" har en nyttolast av typen number, och att händelsen "bar" har en nyttolast av typen string, som i:
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 ) {}
Hur skulle vi definiera EventEmitter-deklarationen så att det är möjligt att definiera händelser och deras typer, och sedan låta användare använda dessa händelser med korrekt typkontroll?
Kanske finns det ett sätt att definiera typen av EventEmitter så att när jag skapar en kan jag skicka ett typargument som innehåller alla förväntade typer?
Finns det ett sätt att göra det dynamiskt efter skapandet?
Svar #1
Jag skulle börja med något sådant här:
interface Events {
foo: number
bar: string
}
interface EventEmitter<T> {
on<K extends keyof T>(s: K, listener: (v: T[K]) => void): T[K];
}
declare const emitter: EventEmitter<Events>;
emitter.on('foo', (payload: any) => {
testNumber(payload)
testString(payload)
});
emitter.on('bar', (payload: any) => {
testNumber(payload)
testString(payload)
});
function testNumber( value: number ) {}
function testString( value: string ) {}
Här är ett exempel på TS Playground.
