typescript - 类型 'never[]' 不可分配给类型 '...'

标签 typescript

Type 'never[]' is not assignable to type '...'

由于这个随机错误,我无法在我的类上初始化属性 items。我想将通用类类型扩展到 Array<string>会确保类型始终是字符串数组吗?

class MyClass<TItems extends Array<string>> {
    constructor() {
        this.items = [];
    }

    public items: TItems;
}

给我错误:

Type 'string' is not assignable to type 'TItems'. 'string' is assignable to the constraint of type 'TItems', but 'TItems' could be instantiated with a different subtype of constraint 'string'.ts(2322)

最佳答案

问题

您可能熟悉这样一个事实,即子类型可以分配给父类(super class)型,但反之则不然。因此,在以下代码和内联解释中-

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

在您的代码中,TItemsArray<string> 的子类型, 和 [] 的类型是never[] .

如果您使用 [] as Array<string> 对其进行了类型转换, 父类(super class)型 ( Array<string> ) 无法分配给子类型 TItems . Playground

如果您使用 [] as TItems 对其进行了类型转换,出于同样的原因,类型转换本身就是错误的。 Playground

解决方案

错误可以通过类型转换为消除错误-

class MyClass<TItems extends Array<string>> {
    public items: TItems;

    constructor() {
        this.items = [] as unknown as TItems;
    }
}

Playground

但这可能会导致运行时错误,因为它不是“安全”的类型转换。

为避免运行时错误,正确的方法是初始化 prop items使用类的构造函数 TItems或返回 TItems 的函数而不是 = [] .这将消除类型错误,并确保不会出现运行时错误。两种方式都演示了-

// 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

关于typescript - 类型 'never[]' 不可分配给类型 '...',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66978140/

相关文章:

javascript - NextJS 服务器文件中的 typescript 错误

javascript - res.body 的 TypeScript 类型注解

javascript - 单击父组件中的按钮时从子组件执行函数 : Angular2

typescript - 属性 'id' 在类型 'T' 上不存在。(2339)Typescript 泛型错误

typescript - $event 对象在 Angular 2 中到底做什么?

javascript - Uncaught TypeError : ctorParameters. 映射在更新到 Angular 7 后不是一个函数

html - 如何使用 Angular 6 向表格添加附加功能

angular - Web OTP API Typescript Typings 问题 - TypeScript 中缺少类型

Typescript 允许对 mixins 使用适当的多重继承,但无法创建声明文件

typescript - 使用 CDK 将文件上传到 S3 存储桶