I have a class property that is constructed with an initial value:
private _httpClient: ClientInterface = new HttpURLConnectionClient();
which I want to override if it's passed when instantiating the class:
class Class {
private _httpClient: ClientInterface = new HttpURLConnectionClient();
constructor(httpClient?: ClientInterface) {
if (httpClient) {
this._httpClient = httpClient // replaces existing _httpClient
}
}
}
new Class(httpClient)
I'm migrating this code to TypeScript 4, and I assumed the following would be equivalent:
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)
but it displays Type 'X | undefined' is not assignable to Type 'X'
, which is understandable if I was not using the logical or.
I know I can solve this issue if I do this, but I want to understand why the solution above shows a type error:
class Class {
private _httpClient: ClientInterface;
constructor(httpClient?: ClientInterface) {
this._httpClient = httpClient || new HttpURLConnectionClient()
}
}
new Class(httpClient)
You have slightly misinterpreted what short-circuiting assignment is doing.
a ||= b
is equivalent toa = a || b
, it deals with the left-hand side of the assignment possibly being undefined, not the right-hand side.In your case, that's something like:
(The compiler actually emits
this._httpClient || (this._httpClient = httpClient)
, but it's easier to think about this way.)Your latter version is the other way around (
a = b || a
):Probably the easiest way to implement this would be to use a parameter property with a default value: