如何为 class 之类的 EventEmitter 的事件有效负载分配 TypeScript 类型?
How can I assign a TypeScript type for event payloads for a class like EventEmitter?
我有一个 class 就像 Node 的 EventEmitter(它甚至可以是相同的 class)。
如何以可以指定每个不同事件名称的回调类型的方式输入它?
例如,我希望 "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 的类型,以便在创建 EventEmitter 时传递一个包含所有预期类型的类型参数?
有没有办法在创建后动态的做?
我会从这样的事情开始:
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 ) {}
这是一个 example on TS Playground。
我有一个 class 就像 Node 的 EventEmitter(它甚至可以是相同的 class)。
如何以可以指定每个不同事件名称的回调类型的方式输入它?
例如,我希望 "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 的类型,以便在创建 EventEmitter 时传递一个包含所有预期类型的类型参数?
有没有办法在创建后动态的做?
我会从这样的事情开始:
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 ) {}
这是一个 example on TS Playground。