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

TypeScript如何正确推断包含多个Error子类的函数返回值类型

问题描述

我有一个函数可以返回number、Error或者NegativeError类型的值,代码示例如下:

class NegativeError extends Error {
  name = 'NegativeError'
}

function doThing (a: number): number | NegativeError | Error {
  return a < 0 ? new NegativeError() : a === 0 ? new Error() : a
}
const done = doThing(1) // number | NegativeError | Error

但是当我移除函数签名中的显式返回类型后,TypeScript会忽略Error类型,仅推断返回类型为number | NegativeError:

function doThing (a: number) {
  return a < 0 ? new NegativeError() : a === 0 ? new Error() : a
}
const done = doThing(1) // number | NegativeError

我目前可以通过一个hack方案强制保留所有离散返回类型:使用构造函数实现,且可以维持原型继承关系,代码如下:

function NegativeError(message: string) {
  Error.call(this)
  this.message = message
  this.name = 'NegativeError'
}
NegativeError.prototype = Object.create(Error.prototype)
NegativeError.prototype.constructor = NegativeError

但我不想使用该方案,因为它可读性差,还会触发TypeScript报错:An outer value of 'this' is shadowed by this container。请问有没有方法可以让TypeScript正确推断所有返回类型?


解决方案

这个问题是TypeScript结构化类型系统的正常表现:你定义的NegativeError继承自Error,且没有显式标注name属性的字面量类型,TS会将name推断为通用string类型,此时NegativeError和原生Error结构完全兼容,TS在推断联合类型时会自动折叠父类型,只保留子类型NegativeError,所以原生Error类型会被“吞掉”。

你可以通过以下几种简洁的方案解决,完全不需要用老式构造函数的hack写法:

  • 方案1:给自定义Error类的name属性加显式字面量类型声明,让TS识别到它和原生Error的结构差异

    class NegativeError extends Error {
      // 显式标注name为固定字面量类型,不再是通用string
      name: 'NegativeError' = 'NegativeError'
    }
    
    function doThing (a: number) {
      return a < 0 ? new NegativeError() : a === 0 ? new Error() : a
    }
    // 此时会正确推断返回类型为 number | NegativeError | Error
    const done = doThing(1)
    
  • 方案2:如果不想修改自定义Error类的定义,可以在返回原生Error的位置加个弱类型断言,强制TS保留该类型

    function doThing (a: number) {
      return a < 0 ? new NegativeError() : a === 0 ? new Error() as Error : a
    }
    
  • 方案3:如果函数返回类型固定,更推荐直接显式声明函数返回类型,既能避免类型推断的偏差,也能提升代码的可维护性,后续修改函数逻辑时如果意外改变返回类型TS会直接提示报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:54:06