TypeScript 2.4.2中Array()结合fill数组的类型检查疑问
这是TypeScript的预期行为,不是Bug
先把两种场景的代码明确列出来,方便对照理解:
// 触发TS2322错误:Type 'number[]' is not assignable to type '{ coin: number; }[]' const errorArr: { coin: number }[] = [1, 2, 3]; // 编译完全通过,无任何报错 const successArr: { coin: number }[] = Array(3).fill(1);
下面拆解背后的核心原因:
为什么第一种情况会报错?
TypeScript对数组字面量的类型推断极其严格。当你写出[1,2,3]时,TypeScript会立刻把它的类型锁定为number[]——因为元素都是数字,没有任何歧义。而你试图把纯数字数组赋值给要求元素是{ coin: number }对象的数组类型,这两个类型完全不兼容(number和{ coin: number }是完全不同的类型),所以类型检查器直接抛出TS2322错误,这是标准的类型安全校验,完全符合预期。
为什么第二种情况能通过编译?
这要从Array()构造函数的类型行为和fill方法的类型定义说起:
- 当你调用
Array(3)而不指定泛型参数时,TypeScript会把这个数组的初始类型推断为any[]——这是TypeScript对无参数/仅传长度参数构造数组的默认处理,因为它不知道你未来要存什么类型的元素。 - 接着调用
fill(1),虽然填充的是数字,但any[]类型的数组允许存入任何类型的值,所以填充后数组的类型依然是any[]。 - 最后,当你把这个
any[]类型的数组赋值给{ coin: number }[]类型的变量时,TypeScript不会拦你——因为any类型是TypeScript的“类型逃逸舱”,任何类型和any之间的转换都是被允许的,哪怕逻辑上1并不是{ coin: number }类型的对象。
如果想要让第二种情况也触发类型错误(更符合类型安全的预期),你只需要给Array指定泛型参数,明确数组的元素类型:
// 此时会报错:Argument of type 'number' is not assignable to parameter of type '{ coin: number; }' const strictArr: { coin: number }[] = Array<{ coin: number }>(3).fill(1);
说白了,两种场景的差异本质是:数组字面量会被推断为明确的具体类型,而无泛型的Array()构造函数会返回宽松的any[]类型,后者绕过了严格的类型检查。
内容的提问来源于stack exchange,提问作者Rohit Falor
相关产品推荐
相关产品推荐

