Typescript 回归泛型推理
我正在尝试使用 一般的想法是我有一个Typescript 回归泛型推理,typescript,generics,type-inference,Typescript,Generics,Type Inference,我正在尝试使用 一般的想法是我有一个IService接口和一个BaseService抽象类。抽象类有一个origin属性,它是IService的一个实例,所有未实现的调用都被转发到此对象BaseService公开一个静态方法wrap,该方法创建装饰器的新实例,并将其源设置为作为参数提供的服务实例 这种方法的功能不是问题,当我尝试指定类型时,问题就出现了。出于某种原因,当我尝试用VerificationService装饰MongoService时,原始类型被减少为iSeries设备,返回值的类型是
IService
接口和一个BaseService
抽象类。抽象类有一个origin
属性,它是IService
的一个实例,所有未实现的调用都被转发到此对象BaseService
公开一个静态方法wrap
,该方法创建装饰器的新实例,并将其源设置为作为参数提供的服务实例
这种方法的功能不是问题,当我尝试指定类型时,问题就出现了。出于某种原因,当我尝试用VerificationService
装饰MongoService
时,原始类型被减少为iSeries设备
,返回值的类型是VerificationService&iSeries设备
,而不是所需的VerificationService&MongoService
我的问题是,这是否是由于代码可能导致的协方差/反方差问题而导致的预期行为,或者这是一个bug,编译器只是不知道参数的类型是MongoService。请注意,当我试图装饰一个没有添加任何属性的类的实例时,类型是正确推断的(第37行)我不能100%确定为什么会发生这种情况,但是如果您查看
包装器的类型和验证服务的构造函数(继承自基本服务
)我们知道为什么会这样。构造函数的参数是ISerivce
而不是泛型类型,因此最简单的假设是在wrap
中推断U
到IService
,而wrap
的第二个参数满足IService
的要求,因此一切都很好,没有理由进一步研究
最简单的解决方案是更改包装器的类型,因为参数可以是任何服务:
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
static wrap(this:{new(origin:IService):T},origin:U):T&U{
以T&U的形式返回新的代理(新的此(原始){
获取(目标:T&U,道具:T的钥匙| U的钥匙){
if(isOverriden(target,prop))返回target[prop];
返回目标。原点[prop];
}
})
}
//一切按预期进行
const serviceInferedinRightly=VerificationService.wrap(新的MongoService());//验证服务和MongoService
const serviceInferedRightly=VerificationService.wrap(新SimpleService());//验证服务和简单服务
const serviceSpecified=VerificationService.wrap(新的MongoService());//验证服务和MongoService