Typescript泛型将函数参数用作可选参数

Typescript泛型将函数参数用作可选参数,typescript,typescript-generics,Typescript,Typescript Generics,我正在尝试通过管道将api调用传递到泛型方法。。我需要能够推导出参数,以便键入分派方法 如果我要使用参数类型,我将需要使用所有类似于dispatcher.dispatch([“这是我的数据,…])的参数进行调度调用,这也不是主要问题 主要的问题是,我不能一般地推断参数是否是可选的。。因此,在下面的示例中,dispatcher.dispatch()中断 class Dispatcher<T extends object, K extends FunctionKeys<T>, P

我正在尝试通过管道将api调用传递到泛型方法。。我需要能够推导出参数,以便键入分派方法

如果我要使用
参数
类型,我将需要使用所有类似于
dispatcher.dispatch([“这是我的数据,…])的参数进行调度调用
,这也不是主要问题

主要的问题是,我不能一般地推断参数是否是可选的。。因此,在下面的示例中,
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
类调度器无效?P:从来没有>{
私有只读方法:K;
私有只读筛选器:(侦听器:任意)=>布尔值;
私有只读listenerResolver:()=>任意[];
构造函数(方法:K,listenerResolver:()=>any[]){
这个方法=方法;
this.listenerResolver=listenerResolver;
this.filter=(listener:any)=>!!listener[this.method];
}
调度(arg:P){
const listeners=this.listenerResolver();
listeners.filter(this.filter).forEach((listener:T)=>listener[this.method](arg));
}
}
接口侦听器{
动作(数据?:字符串):无效;
}
const dispatcher=new dispatcher(“action”,()=>[]);
dispatcher.dispatch(“这是我的数据”);
dispatcher.dispatch();//这一行不编译

想法?

诀窍是为
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 :)
类调度器无效?P:从不>{
私有只读方法:K;
私有只读筛选器:(侦听器:任意)=>布尔值;
私有只读listenerResolver:()=>记录[];
构造函数(方法:K,listenerResolver:()=>记录[]){
这个方法=方法;
this.listenerResolver=listenerResolver;
this.filter=(listener:any)=>!!listener[this.method];
}
//下解
分派(…arg:P扩展未定义?[]:[P]){
const listeners=this.listenerResolver();
listeners.filter(this.filter.forEach((listener)=>listener[this.method](arg));
}
}
接口侦听器{
动作(数据?:字符串):无效;
}
const dispatcher=new dispatcher(“action”,()=>[]);
dispatcher.dispatch(“这是我的数据”);
dispatcher.dispatch();//此行编译:)
解决方案在
dispatch
方法参数类型中可见:

…arg:p扩展未定义?[]:[P]

我们的意思是,如果
p
扩展了
未定义的
,并且optional属性扩展了,那么参数列表是空的
[]
,所以没有参数,但是如果有一个非可选的参数,那么它是必需的。希望能有帮助