TypeScript中的泛型类型参数推理优先级
我有以下类装饰工厂接受初始化函数作为其参数。 在这个initializer
函数中,我想返回一个对应于相关类类型(或派生类)的实例:
function JsonObject<T>(initializer: (json: any) => T) {
return function (target: { new (...args: any[]): T }) {
// ...
}
}
@JsonObject(function (json) {
return new Animal();
})
class Animal {
name: string;
}
返回确切类的实例(如上所述)正常工作,但...
简洁版本
返回派生类的实例不会。 我可以返回一个基本实例,但不是派生的实例。 例如,我不能返回一个Cat
:
@JsonObject(function (json) {
return new Cat(); // Error.
})
class Animal{
name: string;
}
class Cat extends Animal {
color: string;
}
即使猫是一种动物。 然而,我可以为一只猫返回一只动物而不是猫(这是错误的,因为动物不一定是猫)
@JsonObject(function (json) {
return new Animal(); // OK, but it shouldn't be
})
class Cat extends Animal {
color: string;
}
长版本
JsonObject装饰工厂
JsonObject
函数类似于具有泛型类型参数T
函数,接受返回T
作为其参数的回调函数,并返回接受返回T
的新类型的函数。 后者(返回的函数)显然是类装饰器本身。
编译器不允许我 - 例如 - 从这个initializer
函数(或任何其他不匹配类型)返回一个字符串,这是它应该的。
与子类型有关的问题
但是,当使用子类型时,上述类型签名的行为完全相反:从initializer
函数我可以返回一个基类型,但不是派生类型 - 在2步的中间类上使用时发生以下错误继承模式:
@JsonObject(function (json) {
// Test case: return a base type.
return new Animal(); // OK, but it shouldn't be: an 'Animal' is not a 'Cat'
})
@JsonObject(function (json) {
// Test case: return an exact corresponding type.
return new Cat(); // OK, as it should be
})
@JsonObject(function (json) {
// Test case: return a derived type.
return new Kitty(); // <-- Error, but it should be OK, a Kitty *is* a Cat
})
class Cat extends Animal {
color: string;
}
class Kitty extends Cat {
cutenessFactor: number;
}
错误:输入'Cat'不可分配以键入'Kitty'。 'Cat'类型的属性'cutenessFactor'缺失。
我相信我已经指出了错误的起源,它是由编译器在推断泛型时造成的:泛型类型参数T
从initializer: (json: any) => T
的“T”推断出来initializer: (json: any) => T
,这意味着错误是由具有通用类型Kitty
的JsonObject函数引起的, Cat
明显不能这样分配,因此在这种情况下类装饰器不能在Cat
上使用。
我想这样做, T
是从“返回”类型的target
推断出来的,这可以解决我的问题。 我怎么能做到这一点?
当然,当我明确指定泛型类型参数时,它的工作原理是完美的(但是这带有冗余信息):
@JsonObject<Cat>(function (json) {
return new Kitty(); // OK, since type 'Kitty' is assignable to type 'Cat'
})
class Cat extends Animal { }
你的意思是链接装饰者还是你的意思是:
function JsonObject<T>(initializer: (json: any) => T) {
return function (target: { new (...args: any[]): T }) {
return null;
}
}
@JsonObject(function (json) {
return new Foo();
})
class Foo {
foo: string;
}
@JsonObject(function (json) {
// Test case: return an exact corresponding type.
return new Bar(); // OK, as it should be
})
class Bar extends Foo {
bar: string;
}
@JsonObject(function (json) {
// Test case: return a derived type.
return new Baz(); // Ok
})
class Baz extends Bar {
baz: string;
}
如果你的意思是上面的^,它编译得很好
链接地址: http://www.djcxy.com/p/43155.html上一篇: Generic type parameter inference priority in TypeScript