interface myGenericInterface<T> {
propX : T;
}
class implementationA implements myGenericInterface<string> {
propX : string;
}
class implementationB implements myGenericInterface<number> {
propX : number;
}
class sample<T> {
prop : myGenericInterface<T>;
constructor( x : any) {
if(typeof x === "string"){
prop = new implementationA(); // Error reported here. how do I achieve this?
}
}
}
线路错误 -prop = new implementationA()
媒体资源"内容"的类型不兼容。 类型"字符串"不可分配给类型"T"。 "T"可以用与"字符串"无关的任意类型实例化
在这种情况下使用泛型的正确方法是什么?如何有条件地设置具有myGenericInterface
类型的类属性。
问题
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
或T
是string
的子集。 所以我们必须使用as
来抑制打字稿错误。
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>
}
}
}
<小时 />良好的解决方案
我们可以保证任何类型(不仅仅是string | number
)的类型安全,如果我们只是创建实现myGenericInterface<T>
的对象。 如果我们将propX
设置为x
,那么我们不需要知道或关心T
的实际类型是什么,因为我们知道x
可以分配给T
所以{propX: x}
可以分配给myGenericInterface<T>
。
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);
}
}
打字稿游乐场链接
通过class sample<T> {
,您将T
绑定到某种可能既不string
也不number
的未知类型。如果T
例如number[]
(数组),则prop
的类型myGenericInterface<number[]>
不能分配类型为myGenericInterface<string>
的值。
你能做的是改为
class sample {
prop : myGenericInterface<string|number>;
constructor( x : any) {
if(typeof x === "string"){
this.prop = new implementationA(); // Now works
}
}
}
操场