如何排除值为undefined并精简嵌套if/else代码?
问题描述
我有一段可正常运行的代码:
(err, resp) => { if (resp) { if (resp.missing) { resolve(new CacheListFetch.Miss()); } else if (resp.found) { resolve(new CacheListFetch.Hit(resp.found.values)); } else { resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); } } else { resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); } }
为了消除重复的错误处理分支,遵循DRY原则,我尝试了如下重构:
(err, resp) => { switch (true) { case typeof resp === 'undefined': default: resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); break; case resp.missing instanceof cache_client._ListFetchResponse._Missing: resolve(new CacheListFetch.Miss()); break; case resp.found instanceof cache_client._ListFetchResponse._Found: resolve(new CacheListFetch.Hit(resp.found.values)); break; } }
但TypeScript的ESLint持续提示resp可能为undefined,尽管对应分支中resp不可能是undefined:
src/internal/cache-client.ts:303:18 - error TS18048: 'resp' is possibly 'undefined'. 303 case resp.missing instanceof ~~~~ src/internal/cache-client.ts:307:18 - error TS18048: 'resp' is possibly 'undefined'. 307 case resp.found instanceof cache_client._ListFetchResponse._Found: ~~~~ src/internal/cache-client.ts:308:46 - error TS18048: 'resp' is possibly 'undefined'. 308 resolve(new CacheListFetch.Hit(resp.found.values)); ~~~~
请问如何实现代码精简并解决该类型提示问题?
解决方案
方法一:提前处理错误分支,缩小类型范围
先单独处理resp为undefined的情况,后续逻辑中TypeScript会自动推断resp非undefined,同时消除重复代码:
(err, resp) => { if (!resp) { resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); return; } if (resp.missing instanceof cache_client._ListFetchResponse._Missing) { resolve(new CacheListFetch.Miss()); } else if (resp.found instanceof cache_client._ListFetchResponse._Found) { resolve(new CacheListFetch.Hit(resp.found.values)); } else { resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); } }
方法二:类型守卫+Switch结构
若偏好Switch写法,同样先通过提前return完成类型收窄,再处理分支:
(err, resp) => { if (!resp) { resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); return; } switch (true) { case resp.missing instanceof cache_client._ListFetchResponse._Missing: resolve(new CacheListFetch.Miss()); break; case resp.found instanceof cache_client._ListFetchResponse._Found: resolve(new CacheListFetch.Hit(resp.found.values)); break; default: resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); break; } }
方法三:非空断言(不推荐)
如果必须保留原Switch结构,可使用非空断言!强制告诉TypeScriptresp非undefined,但这种方式会跳过类型检查,存在潜在风险,仅在逻辑绝对确定时使用:
(err, resp) => { switch (true) { case typeof resp === 'undefined': default: resolve(new CacheListFetch.Error(cacheServiceErrorMapper(err))); break; case resp!.missing instanceof cache_client._ListFetchResponse._Missing: resolve(new CacheListFetch.Miss()); break; case resp!.found instanceof cache_client._ListFetchResponse._Found: resolve(new CacheListFetch.Hit(resp!.found.values)); break; } }
内容的提问来源于stack exchange,提问作者Schwern
相关产品推荐
相关产品推荐

