回归泛型类型推断
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回归泛型类型推断相关的知识,希望对你有一定的参考价值。
Demo code in the TypeScript playground
我正在尝试使用ES6's Proxy
object创建一个更动态的装饰器模式实现。
一般的想法是我有一个IService
接口和一个BaseService
抽象类。抽象类有一个origin
属性,它是IService
的一个实例,所有未实现的调用都被转发到这个对象。 BaseService
公开了一个静态方法wrap
,它创建了一个装饰器的新实例,并将其原点设置为作为参数提供的服务实例。
这种方法的功能不是问题,当我尝试指定类型时会出现问题。出于某种原因,当我尝试用MongoService
装饰VerificationService
时,原点类型减少到IService
,返回值是VerificationService & IService
类型而不是所需的VerificationService & MongoService
。
我的问题是这是否是预期的行为,因为代码可能导致一些协方差/反差方法问题,或者它是否是一个错误,编译器只是不知道参数的类型是MongoService。请注意,当我尝试装饰不添加任何属性的类的实例时,正确推断出类型(第37行)
我不是100%确定为什么会发生这种情况,但是如果你看一下wrapper
的类型和VerificationService
的构造函数(继承自BaseService
),我们就会知道为什么会这样。构造函数的参数是ISerivce
不是泛型类型,因此最简单的假设是在U
中将IService
推断为wrap
,而wrap
的第二个参数满足IService
所以它一切正常,没有理由进一步查看。
最简单的解决方案是更改wrapper
的类型,因为参数可以是任何服务:
static wrap<U extends IService, T extends BaseService>(this: { new(origin: IService): T }, origin: U): T & U {
return new Proxy(new this(origin) as T & U, {
get(target: T & U, prop: keyof T | keyof U) {
if (isOverriden(target, prop)) return target[prop];
return target.origin[prop];
}
})
}
// All work as expected
const serviceInferedIncorrectly = VerificationService.wrap(new MongoService()); // VerificationService & MongoService
const serviceInferedCorrectly = VerificationService.wrap(new SimpleService()); // VerificationService & SimpleService
const serviceSpecified = VerificationService.wrap<MongoService, VerificationService>(new MongoService()); // VerificationService & MongoService
以上是关于回归泛型类型推断的主要内容,如果未能解决你的问题,请参考以下文章
为啥 TypeScript 中的方法链接会导致泛型类型推断失败?