假设我有两个求和类型(F
和 G
),它们的成员是一对一的关系(即,strings
与 boolean
一起使用,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
和 G
各有 15/20 个成员的情况下,是否有一种不同的方法可以很好地工作?
最佳答案
联合中的成分不是位置性的,因此您永远不应依赖特定类型在联合中的位置。
如果您使用元组来定义 F
和 G
,那么我们可以在剩余参数中使用元组来获取正确的签名并使用映射类型来合并两个元组合并为一个元组:
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]
关于javascript - 如何限制函数签名只接受特定的类型参数对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58076090/