如何为number或bigint类型的算术运算编写正确的TypeScript类型?
TypeScript中number | bigint联合类型的运算符兼容性问题
问题描述
尝试编写支持number或bigint类型的函数,利用JavaScript算术运算符的多态性返回同类型结果,但TypeScript静态类型检查报错。最小复现示例:
const foo = (): number | bigint => 3n let single = foo() let double = single + single // 错误:Operator '+' cannot be applied to types 'number | bigint' and 'number | bigint'.(2365)
逻辑上无论single实际是number还是bigint,自身相加都是合法操作,但TS无法识别该场景。泛型环境下同样存在问题:
type Widen<T extends number | bigint> = T extends bigint ? bigint : number function foo<T extends number | bigint>(n: T): Widen<T> { let single = n as Widen<T> return single + single // 同样触发2365错误 }
解决方案
1. 类型断言(快速临时方案)
通过类型断言告知TS当前操作的安全性:
// 非泛型场景 let double = single + (single as typeof single) as number | bigint; // 泛型场景 type Widen<T extends number | bigint> = T extends bigint ? bigint : number function foo<T extends number | bigint>(n: T): Widen<T> { let single = n as Widen<T> return (single + single) as Widen<T> }
2. 函数重载/泛型条件分支
通过明确类型分支让TS识别合法运算:
// 函数重载实现 function add(x: number): number; function add(x: bigint): bigint; function add(x: number | bigint): number | bigint { return x + x; } // 泛型条件分支实现 type AddResult<T extends number | bigint> = T extends number ? number : bigint; function add<T extends number | bigint>(x: T): AddResult<T> { return x + x as AddResult<T>; }
这种方式能让TS准确推断返回类型,同时消除类型错误。
官方相关Issue
社区中已有类似讨论,最相关的是Issue #41741,该议题围绕any与bigint相加的类型兼容性展开,本质上和当前问题一致——TS类型系统暂无法自动识别联合类型中所有分支均支持的同类型运算符操作。目前该议题仍在讨论阶段,尚未完全解决。
关于类型系统局限性
这属于TypeScript静态类型系统的局限性,而非缺陷。TS对联合类型的运算符检查要求所有分支组合都合法,而不仅是同一分支的运算。虽然single + single在运行时只会是合法的同类型相加,但TS无法静态证明这一点,因此报错以避免number + bigint这类会触发运行时错误的非法操作。
内容的提问来源于stack exchange,提问作者Glen Whitney
相关产品推荐
相关产品推荐

