为何有时应使用TypeScript联合类型而非重载?示例解析
TypeScript重载示例中“分离重载错误报错”的含义与原因解析
先贴出官方文档中的示例代码:
function fn(x: string): Moment; function fn(x: number): Moment; function fn(x: number | string) { // When written with separate overloads, incorrectly an error // When written with union types, correctly OK return moment().utcOffset(x); }
注释含义与历史背景
注释里的“用分离重载会错误报错”是TypeScript旧版本(3.3之前)的行为,当前新版本的TS已经修复了这个类型检查逻辑,所以你本地运行不会触发报错。
旧版本报错的核心原因
在TypeScript 3.3及更早版本中,函数重载的实现体内部,参数类型会被判定为所有重载签名参数类型的交集而非并集:
- 示例里两个重载签名的参数分别是
string和number,它们的交集是never(不存在同时属于string和number的值)。 - 此时实现体中的
x会被推断为never类型,而moment().utcOffset()的参数并不接受never类型,因此TS会抛出类型错误。
现在不报错的原因
TypeScript 3.3对重载实现体的类型推断逻辑做了优化:实现体内部的参数类型改为取所有重载签名参数类型的并集。
- 现在示例中
x的类型会被正确推断为string | number,与utcOffset()的参数类型完全匹配,因此不会触发错误。
对比联合类型签名的差异
如果把重载改成单个联合类型签名的写法:
function fn(x: string | number): Moment { return moment().utcOffset(x); }
这种写法在新旧版本的TS中都不会报错,因为参数类型明确为联合类型,TS可以直接匹配utcOffset()的参数要求。
内容的提问来源于stack exchange,提问作者Devin Johw
相关产品推荐
相关产品推荐

