如何将函数签名限制为仅接受特定类型的参数对

时间:2019-09-24 08:28:20

标签: javascript typescript

比方说,我有两个总和类型(此处为FG,其成员之间存在1对1的关系(即stringsboolean和{ {1}}与number一起使用。

我想定义一个函数object,其签名仅允许某些参数对。

我可以很容易地通过函数重载来做到这一点,就像这样:

F -> G -> something

但是随着类型族变得越来越大,这种方法很快就变得不可扩展。是否有其他方法可以在type F = string | number type G = boolean | object function f(x: string, y: boolean): any function f(x: number, y: object): any function f(x: F, y: G): any { return; } f('a', true) // OK f(1, { x: 1 }) // OK f('a', { x: 1 }) // NOT OK F分别拥有15/20个成员的情况下很好地起作用?

1 个答案:

答案 0 :(得分:1)

联合中的组成部分不是位置,因此您永远不应依赖特定类型在联合中的位置。

如果您使用元组来定义FG,那么我们可以在休息参数中使用元组来获得正确的签名,并使用映射类型将两个元组合并为元组:

type F = [string, number]
type G = [boolean, object]
type Merge<F extends any[], G extends any[]> = {
  [P in keyof F]: Parameters<(x: F[P], y: G extends Record<P, any> ? G[P]: never) => void> // [F[P], G[P]] would work as well byt 
}[number]

type FG = Merge<F, G> // this is [string, boolean] | [number, object]
function f(...a: Merge<F, G>): any {
    return;
}

f('a', true)     // OK
f(1, { x: 1 })   // OK
f('a', { x: 1 }) // NOT OK

play

要恢复原始并集,您可以始终使用F[number]G[number]