问题
您可能熟悉这样一个事实,即可以将子类型分配给超类型,但反之亦然。所以,在下面的代码和内联解释中——
class A extends Array<string> {
public myProp!: string
}
// it is ok to assign a subtype to its supertype
// because subtype has atleast all those props/methods
// that a supertype has
declare const a1: A
const array1: Array<string> = a1
// it is an error to assign supertype to one of its subtype
// (until they are structurally same)
// because the supertype (array2) may have some missing props/methods
// (myProp in this case) that its subtype has.
declare const array2: Array<string>
const a2: A = array2
Playground
在您的代码中,TItems 是 Array<string> 的子类型,[] 的类型是 never[]。
如果您使用 [] as Array<string> 对其进行了类型转换,则无法将超类型 (Array<string>) 分配给子类型 TItems。 Playground
如果你用[] as TItems 对它进行了类型转换,那么由于同样的原因,类型转换本身就是错误的。 Playground
解决方案
可以通过类型转换为错误来消除错误-
class MyClass<TItems extends Array<string>> {
public items: TItems;
constructor() {
this.items = [] as unknown as TItems;
}
}
Playground
但这可能会导致运行时错误,因为它不是“安全”的类型转换。
为避免运行时错误,正确的方法是使用 TItems 类的构造函数或返回 TItems 的函数而不是 = [] 来初始化 prop items。这将消除类型错误并确保不会出现运行时错误。两种方式都得到证明-
// if a passed TItems is supposed to class
// we pass that constructor of the class
// constructor of `MyClass`
class MyClass<TItems extends Array<string>> {
public items: TItems;
constructor(ctor: new () => TItems) {
this.items = new ctor();
}
}
class MyArray extends Array<string> {
private myProp!: string
}
const myClassVar = new MyClass(MyArray)
Playground
// if a passed TItems is supposed to be just a type
// we pass a function that will create that object of `TItems`
class MyClass<TItems extends Array<string>> {
public items: TItems;
constructor(fn: () => TItems) {
this.items = fn();
}
}
declare function createObject(): Array<string> & { myProp: string }
const myClassVar = new MyClass(createObject)
Playground