TypeScript 4中使用逻辑或赋值运算符时的类型错误问题咨询
为啥TypeScript里
||=会报类型不兼容错误? 嘿,这个问题其实是TypeScript的类型检查逻辑在搞事情,我来给你掰扯清楚:
首先先回顾你的几种写法:
原来的可行写法
class Class { private _httpClient: ClientInterface = new HttpURLConnectionClient(); constructor(httpClient?: ClientInterface) { if (httpClient) { this._httpClient = httpClient // 这里不会报错 } } }
这里的关键是类型收窄:当你写if (httpClient)时,TypeScript会自动把httpClient的类型从ClientInterface | undefined收窄成ClientInterface——因为只有当httpClient是真值(也就是非undefined、非null等)时,才会进入if块。所以赋值的时候,两边类型完全匹配,自然不会报错。
你尝试的||=写法(报错)
class Class { private _httpClient: ClientInterface = new HttpURLConnectionClient(); constructor(httpClient?: ClientInterface) { this._httpClient ||= httpClient // 报错:Type 'ClientInterface | undefined' is not assignable to type 'ClientInterface' } }
你以为this._httpClient ||= httpClient等价于this._httpClient = httpClient || this._httpClient?其实从运行逻辑看差不多,但TypeScript的类型检查不认这个账:
httpClient的类型是ClientInterface | undefined,这是因为它是可选参数。- TypeScript不知道
this._httpClient在运行时一定是真值(虽然你初始化了一个实例,但TypeScript只会基于类型分析,不会去推断实例的真假性)。 - 所以
this._httpClient || httpClient的结果类型是ClientInterface | undefined——如果this._httpClient是假值(理论上存在这种可能,比如如果HttpURLConnectionClient的实例被定义为假值,但实际不会,但TypeScript不管),那结果就是httpClient,可能是undefined。 - 把
ClientInterface | undefined赋值给类型为ClientInterface的this._httpClient,自然就触发类型不兼容的错误了。
最后那种可行的写法
class Class { private _httpClient: ClientInterface; constructor(httpClient?: ClientInterface) { this._httpClient = httpClient || new HttpURLConnectionClient() } }
这里的逻辑是直接通过||运算符确保了赋值的结果一定是ClientInterface:如果httpClient是undefined,就用new HttpURLConnectionClient()兜底,所以整个表达式的类型是纯ClientInterface,和属性的类型完全匹配,当然不会报错。
简单总结一下:||=的问题在于右边的httpClient可能是undefined,而TypeScript无法保证左边的this._httpClient一定能“覆盖”掉这个undefined的可能性,所以类型检查失败;而if写法通过类型收窄、兜底写法通过直接确保结果类型,都避开了这个问题。
内容的提问来源于stack exchange,提问作者KadoBOT
相关产品推荐
相关产品推荐

