TypeScript联合类型实例调用Renderer为何仅识别为RendererA
问题原因
你遇到的类型提示异常首先和代码定义顺序有关:
当前代码中RendererA、RendererB的定义在class A、class B之后,而const声明不存在变量提升,TypeScript 在推断类 A、类 B 的Renderer属性类型时,还无法拿到两个渲染函数的实际类型,部分版本的 TypeScript 类型提示会优先展示第一个解析完成的函数类型,也就是你看到的仅提示RendererA的问题。你可以把两个渲染函数的定义移动到两个类的前面,就能看到正确的联合类型提示了。
就算调整了定义顺序,Test.Renderer({instance:Test})仍然会触发类型错误,这是 TypeScript 函数参数逆变的正常规则:
- 联合类型的函数在调用时,传入的参数必须同时满足所有联合分支的函数参数要求,也就是参数类型会取所有函数参数的交集
- 这里
RendererA要求参数的instance是A | undefined,RendererB要求参数的instance是B | undefined,因此二者的交集是instance?: A & B - 你传入的
Test是A | B联合类型,无法赋值给A & B交叉类型,因此类型校验不通过。
而Renderer本身的类型默认是typeof RendererA | typeof RendererB联合类型,不会自动转为交叉类型,交叉类型仅出现在调用时的参数约束环节,如果你需要把函数本身作为交叉类型使用,需要手动声明。
解决方案
如果你确实需要直接传入A | B类型的instance,可以手动对Renderer做类型断言,把它转为RendererA & RendererB交叉类型,相当于你主动告知TS这个函数可以兼容两种参数类型:
(Test.Renderer as typeof RendererA & typeof RendererB)({instance:Test});
也可以提前对Test做类型收窄,明确它是A类实例还是B类实例之后再调用对应的Renderer方法,这种方案类型安全性更高。
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

