TypeScript空对象类型{}覆盖泛型函数返回类型的原因
类型推导结果不符合预期的核心原因
你对{}的语义理解是准确的:它确实代表所有非null、非undefined的合法值,是TypeScript内置的顶层类型之一。
出现推导结果和预期不符,本质是TypeScript在做联合类型归一化处理时的固有规则+设计取舍:
- 联合类型会自动剔除被其他成员完全覆盖的子类型:只要类型A的所有合法取值都属于类型B的取值范围,
A | B就会被直接简化为B。 - 对于没有显式添加约束的泛型
T,TS在推导函数返回值阶段会判定:所有非null、非undefined的T取值,都完全属于{}的覆盖范围;而无约束泛型默认不会被特殊标记为可能携带null/undefined分支,因此T | {}会被直接简化收敛为{}。
验证方式
只要给泛型T显式加上包含null/undefined的约束,让T的取值范围存在{}覆盖不到的部分,推导结果就会符合最开始的预期:
const func = <T extends null | undefined | string>(arg: T) => { if (Math.random() < 0.5) { return arg } return {} } // 此时推导类型为:<T extends null | undefined | string>(arg: T) => T | {}
额外说明
这种收敛是TS为了避免泛型推导产生过于复杂的类型做的设计取舍,本身不是100%类型安全的:如果你给示例中无约束的func传入null/undefined作为参数,运行时确实有概率返回传入的null/undefined,但类型层面会被错误推导为{},丢失null/undefined的类型信息。这也是为什么lint规则不推荐在代码中随意使用{}类型,它很容易在隐式推导中造成类型边界模糊,掩盖潜在的类型问题。
内容的提问来源于stack exchange,提问作者KOO
相关产品推荐
相关产品推荐

