如何改写TypeScript的SchemaParameters类型以支持联合类型的参数提取?
解决SchemaParameters处理联合类型的问题
你的问题核心在于条件类型没有对联合类型的分支进行分布式处理。原来的实现用[T] extends [...]把类型包裹在元组里,这会阻止TypeScript的分布式条件类型特性——本来当条件类型的检查目标是联合类型时,TS会自动拆分每个分支单独处理,再把结果合并,但元组包裹后整个联合类型被当成单一整体,导致推断不符合预期。
解决方案:改用分布式条件类型
去掉元组的包裹,直接让T作为条件类型的检查目标,这样每个联合分支会被单独处理,结果自动合并为联合类型:
export type SchemaParameters<T> = // 处理函数类型:提取参数元组 T extends (...args: infer U) => any ? U // 处理void类型:返回空元组 : T extends void ? [] // 处理普通类型:返回单元素元组 : [T];
验证各个场景
现在这个实现能正确处理你提到的所有情况:
- 单个属性的原有逻辑保持正常:
const fromConstant: SchemaParameters<Schema['string']> = ['lorem ipsum']; // 类型为 [string] ✔️ const fromFunction: SchemaParameters<Schema['stringReceiver']> = ['lorem ipsum 2']; // 类型为 [string] ✔️
- 处理
num | stringReceiver联合类型:
const value1: SchemaParameters<Schema['num' | 'stringReceiver']> = ['lorem ipsum']; // 类型为 [number] | [string] ✔️ const value2: SchemaParameters<Schema['num' | 'stringReceiver']> = [123]; // 同样符合类型 ✔️
- 处理两个接收器的联合类型:
const receiverValue: SchemaParameters<Schema['numReceiver' | 'stringReceiver']> = [123]; // 类型为 [number] | [string] ✔️ const receiverValue2: SchemaParameters<Schema['numReceiver' | 'stringReceiver']> = ['hello']; // 同样符合类型 ✔️
可选:合并为单元素联合元组
如果你确实期望结果是[number | string](而非元组的联合),可以进一步调整实现,提取每个分支的元素类型再合并:
export type SchemaParameters<T> = T extends void ? [] : [ T extends (...args: infer U) => any ? U[number] : T ];
这个版本会把所有分支的结果合并到单个元组中,比如SchemaParameters<Schema['num' | 'stringReceiver']>会解析为[number | string]。
内容的提问来源于stack exchange,提问作者River Tam
相关产品推荐
相关产品推荐

