问题
class sample<T> 是一个泛型类,其中this.prop 的类型取决于该实例的泛型类型参数T 的类型。
通常会设置一个泛型类,以便从传递给构造函数的参数中推断出实例的T 类型。您的构造函数只有(x : any),因此T 的类型将始终为unknown,除非您通过调用new sample<string>("") 显式设置它。
参数x 是any,所以可以调用new sample<number>("")。在这种情况下,T 是 number。但是typeof x === "string" 是true,所以您将设置this.prop,它必须是myGenericInterface<number> 到implementationA,即myGenericInterface<string>。所以希望你能明白为什么 Typescript 在这一行给你一个错误。
平庸的解决方案
我认为您想要做的是将x 设为T 类型并限制T 使其只能是string 或number。
您可以这样做,但它不是 100% 类型安全的,因为它要求我们做出一个可能正确但我们不能保证的断言。当我们检查typeof x === "string" 时,会将x 的类型细化为string,但不会细化T 的类型,因为从技术上讲T 是联合string | number 或@ 987654352@ 是string 的子集。所以我们必须使用as来抑制Typescript错误。
class sample<T extends string | number> {
prop: myGenericInterface<T>;
constructor(x: T) {
if (typeof x === "string") {
// x is known to be string, but we don't know that T is string
this.prop = new implementationA() as myGenericInterface<T>
} else {
this.prop = new implementationB() as myGenericInterface<T>
}
}
}
很好的解决方案
如果我们自己创建实现myGenericInterface<T> 的对象,我们可以保证任何类型(不仅仅是string | number)的类型安全。如果我们将propX 设置为x,那么我们不需要知道或关心T 的实际类型是什么,因为我们知道x 可以分配给T,所以{propX: x} 可以分配给@ 987654364@.
class sample<T> {
prop: myGenericInterface<T>;
constructor(x: T) {
this.prop = {
propX: x,
}
}
}
您可以通过使用泛型类来实现myGenericInterface<T>,从而通过额外的步骤使用相同的方法。
class GenericImplementation<T> implements myGenericInterface<T> {
propX: T;
constructor(value: T) {
this.propX = value;
}
}
class sample<T> {
prop: myGenericInterface<T>;
constructor(x: T) {
this.prop = new GenericImplementation(x);
}
}
Typescript Playground Link