Flow继承机制是否存在异常?链式调用类型推断问题咨询
Flow类型错误:父类方法返回
this时无法识别子类实例类型 我之前也碰到过这个问题!其实这是Flow静态类型推断的默认行为导致的——和JavaScript动态运行时的逻辑不一样,Flow在静态检查时,默认会把父类A中返回this的方法fooA的返回类型推断为A,而不是实际调用该方法的子类B的实例类型。所以当你链式调用fooA().fooB()时,Flow会觉得“我拿到的是A类型的实例,它没有fooB方法啊”,于是抛出类型错误。
不过有两种简单的办法可以解决这个问题:
方法一:使用泛型约束父类的this类型
通过给父类添加泛型参数,让Flow明确知道方法返回的是子类的实例类型:
class A<T: A<T>> { fooA (): T { console.log('fooA called') return (this: any) // 这里用any做临时转换,帮助Flow完成类型推断 } } class B extends A<B> { fooB () { console.log('fooB called') return this } } new B().fooA().fooB() // Flow不再报错
这里泛型T被约束为A<T>,子类B继承时传入B作为泛型参数,这样fooA的返回类型就被指定为B,Flow就能识别后续可以调用fooB了。
方法二:使用Flow的this类型注解
Flow专门提供了this类型,用来表示当前调用方法的实例的实际类型,直接用它注解方法返回值更简单:
class A { fooA (): this { console.log('fooA called') return this } } class B extends A { fooB (): this { console.log('fooB called') return this } } new B().fooA().fooB() // 完美解决类型错误
这种方式下,Flow会自动在子类继承时把fooA的返回类型解析为B,完全符合JavaScript运行时的实际行为。
顺便提一句:JavaScript运行时没问题是因为它是动态类型,this的指向在运行时才确定,调用fooA时this确实是B的实例,所以返回后自然能调用fooB。但Flow是静态检查,需要我们给它一点提示才能正确识别这种继承场景下的this类型。
内容的提问来源于stack exchange,提问作者Clemens
相关产品推荐
相关产品推荐

