为何含空对象变量的数组无法通过object[]类型校验?
TypeScript 5.4.5中object[]类型校验的异常情况解析
这不是TypeScript的Bug,而是由类型推断规则和**{}类型与object类型的差异**共同导致的,具体原因如下:
核心差异点
- 声明
let emptyObject = {}时,TypeScript会自动推断其类型为{}(空对象类型),而非object类型。 {}类型的特殊兼容性:它允许所有值(包括原始类型boolean、number等)赋值给它——因为在JavaScript中,原始类型可以被自动装箱为对象(比如true.toString()是合法调用),所以TypeScript认为原始类型兼容{}类型。object类型则严格限制为非原始类型(对象、数组、函数等),原始类型无法直接赋值给object。
为什么会出现不同的校验结果
1. 使用空对象变量时无报错
let emptyObject = {}; let objectArray : object[] = [emptyObject, true, 1]; // 无编译错误
- TypeScript首先推断数组的类型为
{}[](因为emptyObject是{}类型,且true、1兼容{}类型)。 - 由于
{}类型属于object类型的子类型(空对象是对象的一种),{}[]可以被赋值给object[],因此不会触发报错。但实际上数组中的true和1是原始类型,并不符合object[]的预期——这是{}类型的兼容性带来的“副作用”。
2. 直接使用空对象字面量或非空对象变量时报错
let objectArray2 : object[] = [{}, true, 1]; // 报错:类型'boolean'不能赋值给'object' let nonEmptyObject = {a: 1}; let objectArray3 : object[] = [nonEmptyObject, true, 1]; // 报错:类型'boolean'不能赋值给'object'
- 当直接赋值数组字面量给
object[]时,TypeScript会启用上下文类型:它会用object作为数组每个元素的目标类型,逐一检查元素是否能赋值给object。 {}字面量会被直接推断为object类型(而非{}类型),nonEmptyObject的类型是{a: number}(同样属于object的子类型),但true、1是原始类型,无法赋值给object,因此触发预期的报错。
解决方案
如果你想严格限制数组元素为非原始类型的对象,可以:
- 显式给空对象变量指定
object类型:let emptyObject: object = {}; let objectArray : object[] = [emptyObject, true, 1]; // 触发报错,符合预期 - 使用
Record<string, never>替代{}类型,它会严格限制为空对象,不兼容原始类型:let emptyObject: Record<string, never> = {}; let objectArray : object[] = [emptyObject, true, 1]; // 触发报错,符合预期
内容的提问来源于stack exchange,提问作者klues
相关产品推荐
相关产品推荐

