TypeScript函数重载场景下类属性引用不可访问this类型报错问题
报错成因
- TypeScript在类属性初始化阶段,对带重载签名的函数返回值的类型推断能力有限:没有重载时,
create返回的函数类型是简单的单签名(d?: string) => R | string,TS可以直接将泛型参数R和当前实例的this类型绑定,完成类型推断。 - 添加上重载后,返回的函数是多签名的复合重载类型,TS的类型推断系统无法在类属性初始化的上下文下,安全地把不可外部访问的实例
this类型绑定到重载函数的泛型参数中,因此抛出需要手动添加类型注解的错误。普通的硬编码类型注解又无法适配子类继承时的this类型变化,所以不能解决问题。
解决方案
可以通过明确定义重载函数的泛型类型,搭配类的多态this类型注解实现需求,既保留正确的类型推断,也支持子类继承:
首先先定义create返回的重载函数的泛型类型别名:
// 明确声明wrap函数的重载签名类型 type Wrap<R> = { (d: string): string (): R }
修改create函数,明确标注返回类型为上面定义的Wrap<R>:
function create<R>(returnValue: R): Wrap<R> { function wrap(d: string): string function wrap(): R function wrap(d?: string): R | string { if (d) return d return returnValue } return wrap }
修改类的实现,将prop的赋值放到构造函数中,用多态this作为泛型参数标注prop的类型:
class A { // 用多态this作为泛型参数,适配子类继承时的类型变化 prop!: Wrap<this> constructor() { this.prop = create(this) } } class B extends A { isB = true }
此时所有测试代码都可以正常通过类型校验:
const a: A = new A().prop() // 类型正确,返回A实例 const b: B = new B().prop() // 类型正确,返回B实例,自动适配子类类型 const str: string = b.prop('something') // 类型正确,返回字符串
这个方案完全没有硬编码固定的类类型,依赖TS原生的多态this能力自动适配所有继承自A的子类类型,同时完整保留了wrap函数的重载类型推断效果。
内容的提问来源于stack exchange,提问作者timoxley
相关产品推荐
相关产品推荐

