TypeScript如何为接受扁平可变参数对的函数定义类型?
实现扁平参数的函数签名类型定义
1. 简单Pair类型场景
对于简单的Pair类型:
type Pair = { type: string, value: number };
我们可以通过可变元组类型和递归类型实现扁平参数的约束,确保参数以type+value的成对形式传入,同时生成对应的Pair[]返回类型。
类型定义:
// 递归将多组 [string, number] 转为扁平参数列表 type FlattenedPairs<T extends any[] = []> = T extends [infer H, ...infer R] ? H extends [string, number] ? [...H, ...FlattenedPairs<R>] : never : []; // 从扁平参数推导返回的Pair数组类型 type PairsFromFlattened<T extends any[]> = T extends [string, number, ...infer R] ? [Pair, ...PairsFromFlattened<R>] : []; // 函数签名 declare function makePairs<T extends [string, number, ...any[]]>( ...args: FlattenedPairs<T> ): PairsFromFlattened<FlattenedPairs<T>>;
使用示例:
// 合法调用:参数成对且类型匹配 const pairs = makePairs("a", 1, "b", 2); // 返回类型为 Pair[] // 错误调用:参数个数奇数或类型不匹配 makePairs("a", "b", 2); // 类型报错 makePairs("a", 1, 2); // 类型报错
2. 复杂联合Pair类型场景
已知联合类型Pair及辅助类型PairType、PairOfType、ValueOfType、PairTuple(基于常规场景推导辅助类型定义,若你的实际定义不同可微调):
type StrPair = { type: 's', value: string }; type IntPair = { type: 'i', value: number }; type BoolPair = { type: 'b', value: boolean }; type Pair = StrPair | IntPair | BoolPair; // 辅助类型定义 type PairType = Pair['type']; type PairOfType<T extends PairType> = Extract<Pair, { type: T }>; type ValueOfType<T extends PairType> = PairOfType<T>['value']; type PairTuple = [PairType, ValueOfType<PairType>];
我们需要让makePairs接受多个展开的PairTuple作为扁平参数,同时严格约束每组type与对应value的类型匹配。
类型定义:
// 递归验证扁平参数,确保每组type和value类型严格对应 type FlattenedUnionPairs<T extends any[] = []> = T extends [infer Type extends PairType, ...infer Rest] ? [Type, ValueOfType<Type>, ...FlattenedUnionPairs<Rest>] : []; // 从扁平参数推导返回的联合Pair数组类型 type UnionPairsFromFlattened<T extends any[]> = T extends [infer Type extends PairType, ValueOfType<Type>, ...infer Rest] ? [PairOfType<Type>, ...UnionPairsFromFlattened<Rest>] : []; // 函数签名 declare function makePairs<T extends PairType[]>( ...args: FlattenedUnionPairs<T> ): UnionPairsFromFlattened<FlattenedUnionPairs<T>>;
使用示例:
// 合法调用:每组type和value类型严格匹配 const pairs = makePairs('s', 'hello', 'i', 123, 'b', true); // 返回类型为 [StrPair, IntPair, BoolPair] // 错误调用:type和value类型不匹配 makePairs('s', 123); // 类型报错('s'对应value应为string) makePairs('i', 'abc'); // 类型报错('i'对应value应为number)
关键说明:
- 两种场景均利用TypeScript的递归条件类型和可变元组类型实现扁平参数的类型约束。
- 复杂联合场景中,通过
PairType与ValueOfType的关联,强制type和value的类型匹配,避免不兼容的调用。
内容的提问来源于stack exchange,提问作者Dan Kadera
相关产品推荐
相关产品推荐

