You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript报错:类型‘void | ISomeModel’不存在属性‘id’的原因及解决方法

问题原因分析

你说得没错,实际运行时这个create函数要么返回ISomeModel要么抛出错误,但TypeScript是基于代码静态分析来推断类型的,它发现了一个潜在的void返回场景:

你的handleFirestoreError方法在处理permission-denied和unauthenticated错误时,只执行了tokenService.logout(true),没有抛出任何错误。这就意味着当触发这类错误时,create函数的catch分支会执行完handleFirestoreError后,默认返回undefined(对应类型void),而不是让Promise进入rejected状态。TypeScript捕捉到了这个逻辑,所以把create的返回类型推断为Promise<ISomeModel | void>。

修复方案

有几种不同的修复方式,推荐从根源上对齐类型和实际逻辑的方案:

方案1:让handleFirestoreError始终抛出错误

既然你希望所有错误场景都会抛出异常,那修改handleFirestoreError,在处理完logout后明确抛出错误:

handleFirestoreError(error: any) { 
  if (error.code === 'permission-denied' || error.code === 'unauthenticated') { 
    tokenService.logout(true); 
    // 新增:抛出错误,确保Promise进入rejected状态
    throw error;
  } else { 
    throw error; 
  } 
}

这样修改后,create函数的catch分支永远会抛出错误,TypeScript就会推断它的返回类型为Promise<ISomeModel>,你的组件调用代码也不会再报错。

方案2:在create的catch分支补充抛出逻辑

如果不想修改handleFirestoreError的原有逻辑,也可以在create的catch块里,调用完错误处理方法后手动抛出错误:

create(someModel: ISomeModel): Promise<ISomeModel> { 
  return db 
    .add(someModel) 
    .then((doc) => SomeService.fromJsonAndId(someModel, doc.id)) 
    .catch((err) => {
      this.handleFirestoreError(err);
      // 确保Promise不会返回void
      throw err;
    }); 
}

方案3:类型断言(不推荐,仅临时绕过)

如果你确定运行时绝不会出现void的情况,可以用类型断言强制告诉TypeScript返回的是ISomeModel:

const someInstance = await someService.create(someModelObj) as ISomeModel; 
console.log('created', someInstance.id);

不过这种方式会跳过TypeScript的类型检查,隐藏潜在的运行时风险,只建议在紧急情况下临时使用。

内容的提问来源于stack exchange,提问作者rahulserver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:02:40