如何用变量参数强类型函数

时间:2018-02-12 16:43:39

标签: typescript

我在打字稿中编写了一个Parser Combinator。其中一个函数是用另一个带有任何类型签名和一些参数的函数,然后调用它:

function f(func, ...args) {
  func.apply(null, args);
}

有没有办法强烈输入这个,以便可以像这样调用函数:

f(
  (s: string) => { console.log(s) },
  "Hello world!"
)

但是,如果参数输入错误或者参数数量不正确,它会失败吗?

f(
  (s: string) => { console.log(s) },
  1234.56 // incorrect type
)

f(
  (s: string) => { console.log(s) },
  "Hello",
  "World" // too many arguments
)

(在f中进行了一些额外处理,这就是我不能直接拨打func的原因。

1 个答案:

答案 0 :(得分:2)

虽然您不能为任意数量的参数执行此操作,但您可以定义一个函数来检查有限数量的参数,并根据需要添加更多:

function f<T1>(func: (a1: T1) => void, a1: T1): void;
function f<T1, T2>(func: (a1: T1, a2: T2) => void, a1: T1, a2: T2): void;
function f<T1, T2, T3>(func: (a1: T1, a2: T2, a3: T3) => void, a1: T1, a2: T2, a3: T3): void;
function f<T1, T2, T3, T4>(func: (a1: T1, a2: T2, a3: T3, a4: T4) => void, a1: T1, a2: T2, a3: T3, a4: T4): void;
// Private signature, not publicly available
function f(func: Function, ...args: any[]): void {
    func.apply(null, args);
}
f(
    (s: string) => { console.log(s) },
    1234.56 // incorrect type
)

f(
    (s: string) => { console.log(s) },
    "Hello",
    "World" // will accept more arguments  
)

以上版本将检查类型,但可以使用更多参数调用它。这是因为将选择具有2种泛型类型的重载,并且func可以具有较少的参数并且仍然是兼容的。

如果您使用2调用方法,可以实现完全安全,该方法在第一次调用中锁定func,并返回已经确定了参数数量的第二个函数:

function f2<T1>(func: (a1: T1) => void): (a1: T1) => void;
function f2<T1, T2>(func: (a1: T1, a2: T2) => void): (a1: T1, a2: T2) => void;
function f2<T1, T2, T3>(func: (a1: T1, a2: T2, a3: T3) => void): (a1: T1, a2: T2, a3: T3) => void;
function f2<T1, T2, T3, T4>(func: (a1: T1, a2: T2, a3: T3, a4: T4) => void): (a1: T1, a2: T2, a3: T3, a4: T4) => void;
// Private2 signature, not publicly available
function f2(func: Function) {
    return function (...args: any[]) { func.apply(null, args) };
}
f2((s: string) => { console.log(s) })(1234.56) // type mismatched 

f2((s: string) => { console.log(s) })(
    "Hello",
    "World" // too many arguments
)