首页 > 解决方案 > 如何将函数签名限制为仅接受特定的类型参数对

问题描述

假设我有两种求和类型(这里是) FG它们的成员是一对一的关系(即,stringsbooleannumber一起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

但是随着类型族的增长,这种方法很快变得无法扩展。有没有一种不同的方法可以在每个成员有 15 / 20 个成员的情况下很好地工作FG

标签: javascripttypescript

解决方案


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

如果您使用元组进行定义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

要取回原来的工会,你总是可以使用F[number]G[number]


推荐阅读