TypeScript泛型比较函数TS7053类型报错问题及修复咨询
修复TypeScript泛型比较函数的类型收窄问题
你的推测完全正确:虽然Array.isArray(a)把a的类型收窄到[number, number],但泛型T依然可能是Compare联合类型(number | [number, number]),TypeScript无法自动推断此时b必然和a是同类型的数组,因此会出现索引访问的类型错误。下面提供几种可靠的修复方案:
方案一:使用函数重载(推荐)
通过函数重载明确不同参数类型的匹配关系,让TypeScript精准推断参数类型,同时提升代码可读性:
type Compare = number | [number, number] // 重载签名:处理数字比较 function compare(a: number, b: number): number; // 重载签名:处理数字元组比较 function compare(a: [number, number], b: [number, number]): number; // 实现签名:统一处理逻辑 function compare(a: Compare, b: Compare): number { if (Array.isArray(a)) { // 此时TypeScript能确定b也是数组,可直接访问索引 let res = compare(a[0], b[0]); if (res !== 0) { return res; } // 补充比较第二个元素(原代码遗漏了这一步) return compare(a[1], b[1]); } else { // 此时TypeScript能确定b也是数字 if (a < b) { return -1; } else if (a > b) { return 1; } } return 0; }
方案二:手动收窄b的类型
如果不想用重载,可以在数组分支里手动断言b的类型,同时保证类型安全(因为a和b都是T类型,当a是数组时b必然也是数组):
type Compare = number | [number, number] function compare<T extends Compare>(a: T, b: T): number { if (Array.isArray(a)) { // 断言b为数组类型 const bArr = b as [number, number]; let res = compare(a[0], bArr[0]); if (res !== 0) { return res; } return compare(a[1], bArr[1]); } else { // 断言b为数字类型 const bNum = b as number; if (a < bNum) { return -1; } else if (a > bNum) { return 1; } } return 0; }
方案三:优化泛型约束(隐式收窄)
如果调用函数时始终传入单一类型的参数(不会直接传入Compare联合类型),可以依赖TypeScript的控制流分析自动收窄类型,但这种方式对函数内部的类型推断依赖更强,不如重载直观:
type Compare = number | [number, number] function compare<T extends Compare>(a: T, b: T): number { if (Array.isArray(a)) { // 当T是单一类型时,TypeScript能推断b和a同类型 let res = compare(a[0], b[0]); if (res !== 0) { return res; } return compare(a[1], b[1]); } else { if (a < b) { return -1; } else if (a > b) { return 1; } } return 0; }
内容的提问来源于stack exchange,提问作者Feuermurmel
相关产品推荐
相关产品推荐

