我正在尝试将api调用通过管道传递给通用方法。.我需要能够推断出参数,以便可以键入dispatch方法。
如果要使用Parameters<T[K]>
类型,则需要使用所有dispatcher.dispatch(["this is my data", ... ])
这样的参数进行调度调用,这也不是主要问题。
主要问题是,我无法一般性地推断参数是否可选。.因此,在下面的示例中,dispatcher.dispatch()
中断了。
class Dispatcher<T extends object, K extends FunctionKeys<T>, P = T[K] extends (p1: infer P) => void ? P : never> {
private readonly method: K;
private readonly filter: (listener: any) => boolean;
private readonly listenerResolver: () => any[];
constructor(method: K, listenerResolver: () => any[]) {
this.method = method;
this.listenerResolver = listenerResolver;
this.filter = (listener: any) => !!listener[this.method];
}
dispatch(arg: P) {
const listeners = this.listenerResolver();
listeners.filter(this.filter).forEach((listener: T) => listener[this.method](arg));
}
}
interface Listener {
action(data?: string): void;
}
const dispatcher = new Dispatcher<Listener, "action">("action", () => []);
dispatcher.dispatch("this is my data");
dispatcher.dispatch(); // this line does not compile
有想法吗?
答案 0 :(得分:0)
技巧是为dispatch
方法的参数创建条件类型。
完整代码(由于您的代码段不完整,我替换了某些类型:
class Dispatcher<T extends object, K extends keyof T, P = T[K] extends (p1: infer P) => void ? P : never> {
private readonly method: K;
private readonly filter: (listener: any) => boolean;
private readonly listenerResolver: () => Record<K, Function>[];
constructor(method: K, listenerResolver: () => Record<K, Function>[]) {
this.method = method;
this.listenerResolver = listenerResolver;
this.filter = (listener: any) => !!listener[this.method];
}
// below solution
dispatch(...arg: P extends undefined ? [] : [P]) {
const listeners = this.listenerResolver();
listeners.filter(this.filter).forEach((listener) => listener[this.method](arg));
}
}
interface Listener {
action(data?: string): void;
}
const dispatcher = new Dispatcher<Listener, "action">("action", () => []);
dispatcher.dispatch("this is my data");
dispatcher.dispatch(); // this line compiles :)
该解决方案在dispatch
方法参数类型中可见:
...arg: P extends undefined ? [] : [P]
我们说的是,如果P
扩展了undefined
,并且可选属性也是如此,则参数列表为空[]
,因此没有参数,但是如果有一个非可选参数,那么这是必需的。希望能帮助到你。