如何在TypeScript中定义可赋值的NumMax<z,z>类型以取两数最大值?
解决TypeScript中NumMax<z,z>无法赋值给z的问题
原定义的问题在于:当z是泛型参数时,[z,z]无法匹配任何枚举的具体数值元组分支,会走到兜底的x,但TypeScript编译器无法在泛型约束下推断出NumMax<z,z>等价于z,导致类型不匹配错误。以下是两种可行解决方案:
方案一:优先处理相等情况(适配原有枚举逻辑)
修改NumMax类型,先判断两个数值类型是否相等,直接返回该类型,再处理不等的场景:
export type NumMax<x extends number, y extends number> = // 优先匹配x和y相等的情况,直接返回x(或y) x extends y ? x : // 原有不等数值的分支判断 [x, y] extends [0, 1] ? 1 : [x, y] extends [0, 2] ? 2 : [x, y] extends [0, 3] ? 3 : [x, y] extends [1, 0] ? 1 : [x, y] extends [1, 1] ? 1 : [x, y] extends [1, 2] ? 2 : [x, y] extends [1, 3] ? 3 : [x, y] extends [2, 0] ? 2 : [x, y] extends [2, 1] ? 2 : [x, y] extends [2, 2] ? 2 : [x, y] extends [2, 3] ? 3 : [x, y] extends [3, 0] ? 3 : [x, y] extends [3, 1] ? 3 : [x, y] extends [3, 2] ? 3 : [x, y] extends [3, 3] ? 3 : x; function func1<x extends number, y extends number>(xx: x, yy: y): NumMax<x, y> { return null as any; // 业务逻辑实现 } function func2<z extends number>(z1: z, z2: z): z { return func1(z1, z2); // 不再报错,NumMax<z,z>直接匹配到x extends y分支,返回z }
方案二:通用数值比较(支持任意数值)
利用TypeScript数组长度的泛型特性实现通用的数值大小比较,无需枚举具体数值:
// 判断数值A是否大于B type IsGreaterThan<A extends number, B extends number> = Array<never> extends { length: A } & { length: infer L } ? Array<never> extends { length: B } & { length: infer M } ? L extends M ? false : [...Array<M>, ...Array<0>] extends [...Array<L>, ...Array<0>] ? false : true : false : false; // 定义通用NumMax类型 type NumMax<X extends number, Y extends number> = X extends Y ? X : IsGreaterThan<X, Y> extends true ? X : Y; function func1<x extends number, y extends number>(xx: x, yy: y): NumMax<x, y> { return null as any; // 业务逻辑实现 } function func2<z extends number>(z1: z, z2: z): z { return func1(z1, z2); // 类型匹配,NumMax<z,z>返回z }
原理说明
- 方案一通过优先匹配
x extends y的分支,直接将NumMax<z,z>解析为z,让编译器明确类型等价关系,解决赋值错误。 - 方案二利用数组长度的泛型比较逻辑,实现了通用的数值大小判断,同时保留
x extends y分支确保NumMax<z,z>直接返回z。
内容的提问来源于stack exchange,提问作者Carucel
相关产品推荐
相关产品推荐

