首页 > 解决方案 > 子一个函数的参数的可选性取决于其他函数打字稿的参数的可选性

问题描述

我正在创建一个函数示例,它将函数 fn1 作为参数并返回函数 fn2;

type Values<T> = (values: T) => Promise<void>;  //function with argument
type NoValues = () => Promise<void>;    //function without arguments
type Func1<T> = Values<T> | NoValues;

let example = function <T, R extends Func1<T> = Func1<T>>(fn1: R) {  
    const fn2 = async (values: R extends Values<T> ? T : void) => { 
        await fn1(values);
    }
    return fn2;
}

fn1 应该采用一个可选参数。根据 fn1 是否有可选参数,fn2 也应该有。所以如果 fn1 没有任何参数,那么 fn2 也不应该有它们,反之亦然。

我尝试用多种方式编写这样的限制,但仍然无法成功。如果有人帮助我,我会很高兴。

interface IExample {
    whatever: string;
}
const test1_fn1 = async () => console.log("");
const test1_fn2 = example<IExample>(test1_fn1);
test1_fn2() //Should work, but does not. Expected 1 argument. Not intended

const test2_fn1 = async (values: IExample) => console.log(values);
const test2_fn2 = example<IExample>(test2_fn1);
test2_fn2() //Should not work, does not work, as intended
test2_fn2({whatever: ""}) //Should work, works, as intended

TS 版本:3.8.3。这里是游乐场

标签: typescriptoverloadingconditional-types

解决方案


重载可能最简单:

type Values<T> = (values: T) => Promise<void>;  //function with argument
type NoValues = () => Promise<void>;    //function without arguments
type Func1<T> = Values<T> | NoValues;

function makeFn2<T>(fn1: NoValues): NoValues;
function makeFn2<T>(fn1: Values<T>): Values<T>;
function makeFn2<T>(fn1: Func1<T>): Func1<T> {  
    return async (...values: [T?]) => { 
        await (fn1 as any)(...values);
    }
}


declare const argFunc: Values<string>;
const argFunc2=makeFn2(argFunc);
argFunc2("s");
argFunc2();  // error

declare const noArgFunc: NoValues;
const noArgFunc2=makeFn2(noArgFunc);
noArgFunc2();
noArgFunc2("asd");  // error

它在编译和运行时都应该是正确的,即只有当 fn2 被调用时才使用参数调用 fn1。


推荐阅读