TypeScript 类使用联合类型字段实现接口导致错误 (2322)

Posted

技术标签:

【中文标题】TypeScript 类使用联合类型字段实现接口导致错误 (2322)【英文标题】:TypeScript Class Implements Interface with Union Type Field results in Error (2322) 【发布时间】:2021-12-30 10:05:18 【问题描述】:

我不明白为什么会出现错误 2322。

请检查以下代码sn-p:

interface Fish 
  alive: string | boolean;


class FishClass implements Fish 
  alive  = 'Yes'

  constructor() 
    // Type 'boolean' is not assignable to type 'string'.(2322)
    this.alive = true; 
  

接口定义了字符串的联合类型|布尔值。

当我将两种可能的类型之一分配给实现接口的类中的字段时,为什么类型是固定的?

【问题讨论】:

【参考方案1】:

尽管大多数人的期望,类成员不是contextually typed,因为它们被声明为实现或扩展的类型。类上的extendsimplements 声明对类实例的类型没有任何影响。相反,它只是在事后根据超类或接口对类进行检查。因此,如果您的类未能实现或扩展您声明的内容,您将收到编译器警告。但是当涉及到生成的类型时,它就像您完全删除了 extendsimplements 子句一样。不,没有人喜欢这个。

请参阅microsoft/TypeScript#3667 以获取解决此问题的原始请求,并尝试在microsoft/TypeScript#6118 但由于现有库的一些问题最终被放弃;见this comment。有几个未解决的问题,包括microsoft/TypeScript#32082;如果你想看到这个问题得到解决,你可能想去那个问题并给它一个?,但现在我们只需要接受这样一个事实:class Foo implements Bar /*...*/Foo 的类型与@987654334 具有相同的含义@ 会。


在您的情况下,这意味着class FishClass implements Fish /*...*/ 在推断成员的方式方面与class FishClass /*...*/ 完全相同。由于alive 属性是用string"Yes" 初始化的,因此编译器将其推断为string 类型。稍后当您将true 分配给它时,这是一个错误,因为您不能将boolean 分配给string。注意string可以赋值给string | boolean,所以对FishClass implements Fish的检查成功;您可以缩小子类型的属性。

目前处理这个问题的正确方法是使用所需的类型手动注释field:

class FishClass implements Fish 
   alive: string | boolean = 'Yes'; // okay

   constructor() 
      this.alive = true; // okay
   

Playground link to code

【讨论】:

以上是关于TypeScript 类使用联合类型字段实现接口导致错误 (2322)的主要内容,如果未能解决你的问题,请参考以下文章

typescript里一些有趣的点

Typescript 类不实现接口类型

如何将联合类型指定为对象键 Typescript

非标准 TypeScript 接口/类字段

Typescript快速入门

使用裸函数签名和其他字段实现 TypeScript 接口