Ошибка типа при использовании логического или с Typescript 4

#typescript #typescript4.0

#typescript #typescript4.0

Вопрос:

У меня есть свойство класса, которое создается с начальным значением:

 private _httpClient: ClientInterface = new HttpURLConnectionClient();
  

который я хочу переопределить, если он передан при создании экземпляра класса:

 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)
  

Комментарии:

1. Я не вижу ошибки на игровой площадке , поскольку я ожидаю if (httpClient) , что она сужается от ClientInterface | undefined до ClientInterface .

2. Я думаю, вы пропустили весь вопрос. Эта часть кода в порядке. Я хочу заменить его на приведенный ниже, используя логическое или ||= , которое выдает: typescriptlang.org/play ? #code/…

3. О, я понимаю, что вы имеете в виду, извините — примечание ||= касается того, что левая сторона , возможно, не определена, а не правая сторона. Это a = a || b не a = b || a так .

4.Вы можете упростить все это, чтобы constructor(private _httpClient: ClientInterface = new HttpURLConnectionClient()) typescriptlang.org/play ?#code/…

Ответ №1:

Вы немного неверно истолковали, что делает назначение короткого замыкания. a ||= b эквивалентно a = a || b , оно имеет дело с тем, что левая часть присваивания, возможно, не определена, а не с правой частью.

В вашем случае это что-то вроде:

 this._httpClient = this._httpClient || httpClient
  

(Компилятор фактически выдает this._httpClient || (this._httpClient = httpClient) , но так проще думать об этом.)

Ваша последняя версия наоборот ( a = b || a ):

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

Вероятно, самым простым способом реализовать это было бы использовать свойство параметра со значением по умолчанию:

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