TypeScript如何约束映射类型泛型参数,实现统一State入参的zipAll函数
解决方案
你遇到的问题核心是 TypeScript 无法从T extends State<S, any>[]这类泛型约束中反向推导S的类型,我们可以调整泛型设计,先接收全部入参的类型,再通过条件类型校验S的一致性,实现单个函数签名满足需求:
type State<S, A> = (s: S) => readonly [S, A]; type MapResults<T extends State<any, any>[]> = { [K in keyof T]: T[K] extends State<any, infer A> ? A : never }; // 校验所有State的状态类型是否完全一致 type AllSameState<T extends State<any, any>[], S = T[number] extends State<infer _S, any> ? _S : never> = T extends [infer Head, ...infer Tail extends State<any, any>[]] ? Head extends State<S, any> ? AllSameState<Tail, S> : false : true declare function zipAll<T extends State<any, any>[]>( ...states: AllSameState<T> extends true ? T : never[] ): T extends State<infer S, any>[] ? State<S, MapResults<T>> : never
效果验证
declare const s0: State<number, string>; declare const s1: State<number, boolean>; declare const sBad: State<string, symbol>; // 正常推导:返回 State<number, [string, boolean]> const res1 = zipAll(s0, s1); // 正确触发类型错误:存在状态类型不匹配的入参 const res2 = zipAll(s0, s1, sBad);
实现说明
- 不再将状态类型
S作为显式泛型参数声明,避免 TypeScript 推导失败降级为unknown - 先将所有入参的类型收集为泛型
T,通过递归工具类型AllSameState遍历校验每一个入参的S类型是否完全统一 - 校验通过后再从
T中提取统一的S类型和各个入参的返回值类型,组装为最终的聚合State类型
该方案无需函数重载、无需柯里化、无需手动传入任何类型参数,完全自动推导且类型校验严格,支持任意数量的入参。
内容的提问来源于stack exchange,提问作者jmartinezmaes
相关产品推荐
相关产品推荐

