使用 Logical 或 Typescript 4 时出现类型错误

Type error when using Logical or with Typescript 4

我有一个 class 属性 是用初始值构造的:

private _httpClient: ClientInterface = new HttpURLConnectionClient();

如果在实例化 class 时传递了它,我想覆盖它:

class Class {
  private _httpClient: ClientInterface = new HttpURLConnectionClient();

  constructor(httpClient?: ClientInterface) {
    if (httpClient) {
      this._httpClient = httpClient // replaces existing _httpClient
    }
  }
}

new Class(httpClient)

我正在将这段代码迁移到 TypeScript 4,我假设以下内容是等效的:

class Class {
  private _httpClient: ClientInterface = new HttpURLConnectionClient();

  constructor(httpClient?: ClientInterface) {
      this._httpClient ||= httpClient // Shows ts error! But should be equivalent to this._httpClient = httpClient || this._httpClient
  }
}

new Class(httpClient)

但它显示Type 'X | undefined' is not assignable to Type 'X',如果我没有使用逻辑或,这是可以理解的。

我知道如果我这样做可以解决这个问题,但我想了解为什么上面的解决方案显示类型错误:

class Class {
  private _httpClient: ClientInterface;

  constructor(httpClient?: ClientInterface) {
      this._httpClient = httpClient || new HttpURLConnectionClient()
  }
}

new Class(httpClient)

您稍微误解了 short-circuiting assignment 在做什么。 a ||= b 等同于 a = a || b,它处理赋值的 left-hand 侧 可能未定义,而不是 right-hand 侧。

在你的情况下,这类似于:

this._httpClient = this._httpClient || httpClient

(编译器实际上发出this._httpClient || (this._httpClient = httpClient),但这样想更容易。)

你的后一个版本是相反的(a = b || a):

this._httpClient = httpClient || new HttpURLConnectionClient()
                              // ^ equivalent to this._httpClient

可能最简单的实现方法是使用具有默认值的 parameter property

class Class {
  constructor(private _httpClient: ClientInterface = new HttpURLConnectionClient()) { }
}