如何告知TypeScript两个泛型类型为同一类型?
解决方案
你遇到的类型报错本质是TypeScript无法在函数实现内部自动根据重载分支收窄泛型类型,即使你定义了无init参数的重载,TS也无法推导该场景下泛型B和A是同一类型。可以通过重载分离场景+内部类型断言的方式解决,不会影响外部调用的类型安全性:
改后完整代码
// 重载1:无init参数,累计值类型和数组元素类型一致 function scan<A>(this: A[], f: (a: A, x: A) => A): A[]; // 重载2:传入init参数,可自定义累计值类型 function scan<A, B>(this: A[], f: (a: B, x: A) => B, init: B): B[]; // 实现签名:兼容两个重载的类型范围即可 function scan<A, B>(this: A[], f: (a: A | B, x: A) => A | B, init?: B): (A | B)[] { if (init === undefined) { const result = [this[0]]; // 断言当前场景下回调符合A类型约束,和第一个重载逻辑对应 const accumulator = f as (a: A, x: A) => A; for (let i = 1; i < this.length; i++) { result.push(accumulator(result[i - 1], this[i])); } return result; } const result = [init]; // 断言当前场景下回调符合B类型约束,和第二个重载逻辑对应 const accumulator = f as (a: B, x: A) => B; for (let i = 0; i < this.length; i++) { result.push(accumulator(result[i], this[i])); } return result; }
说明
- 把第二个重载的
init从可选改为必选,避免出现调用方传了回调但init传undefined的不合法场景,类型更严谨 - 内部的类型断言是安全的,因为重载已经对外约束了两种调用场景的参数类型,实现逻辑和重载完全对齐,不会出现类型错误
- 外部调用时类型推导完全正常,无init时自动推断返回值为
A[],传init时自动根据init类型推断B的类型
内容的提问来源于stack exchange,提问作者Aadit M Shah
相关产品推荐
相关产品推荐

