为何Typescript做完存在性检查后仍提示对象可能未定义?
TypeScript无法跨变量推断类型的原因说明
核心原因
这是TypeScript控制流分析的现有设计限制:TS不会为普通布尔变量存储它和其它变量/参数之间的隐含逻辑关联。
你定义的const hasError = error || !data;只是一个普通的布尔值变量,TS在类型推导过程中,只会记录hasError的类型是boolean,不会额外留存「hasError为假等价于error为假 且 data一定存在」这个逻辑映射。
因此当进入if (!hasError)分支时,TS只能判断hasError的布尔值为假,不会反向推导出此时data已经不是undefined,仍然会将data的类型判定为Data | undefined,访问属性时就会抛出Object is possibly undefined的错误。
推荐解决方案
你不需要写重复的判断逻辑,可以用以下几种更简洁的方案解决:
- 方案1:直接将判断逻辑内联到if条件中,TS可以直接完成类型收窄:
interface Data { isAvailable: boolean; } const foo = (data: Data | undefined, error: boolean) => { if (!(error || !data)) { // 此处data会被自动推断为Data类型,不会报错 if (data.isAvailable) { // 业务逻辑 } } return error || !data; }
- 方案2:封装带类型谓词的判断函数,显式告知TS判断逻辑对应的类型变化:
interface Data { isAvailable: boolean; } function checkHasError(data: Data | undefined, error: boolean): data is undefined { return error || !data; } const foo = (data: Data | undefined, error: boolean) => { const hasError = checkHasError(data, error); if (!hasError) { // 此处TS可以识别到data一定是Data类型 if (data.isAvailable) { // 业务逻辑 } } return hasError; }
- 方案3:如果你100%确定当前分支下
data一定存在,可以直接使用非空断言!跳过检查,适合逻辑非常确定的简单场景:
if (!hasError) { if (data!.isAvailable) { // 业务逻辑 } }
内容的提问来源于stack exchange,提问作者user15567737
相关产品推荐
相关产品推荐

