当回调的类型依赖于另一个参数时,Typescript很难推断回调的参数,我在几个SO问题中看到了这一点(如果您愿意,我可以搜索一些)。
解决办法是用另一种方式来解决这个问题,那就是使
on
函数有几个重载。诀窍是这样做,而不必重述接口中的所有签名。
您的要求与
this
答案,您将在那里找到更详细的解释,但是根据您的需要修改代码,代码将如下所示:
interface EventEmitter<ListenersT>
{
on : OnAll<ListenersT, this>
}
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type OnSignatures<T, TReturn> = { [P in keyof T]: (event: P, listener: T[P]) => TReturn }
type OnAll<T, TReturn> = UnionToIntersection<OnSignatures<T, TReturn>[keyof T]>
interface MyEvents
{
foo(x: number): void;
bar(): void;
moo(a: string, b: Date): void;
}
interface MyEmitter extends EventEmitter<MyEvents>
{
// on is now equivalent to an on with these overloads
//on(event: 'foo', listener: (x: number) => void): this;
//on(event: 'bar', listener: () => void): this;
//on(event: 'moo', listener: (a: string, b: Date)=> void): this;
}
const my: MyEmitter = <any> {};
my.on('foo', (x) => x / 4); // x is number
my.on('bar', () => 42);
my.on('moo', (a, b) => a + ': ' + b.getFullYear());
Playground link