为何向数组推送缺省属性对象时TypeScript未报错?
以下是我们的类型定义:
type ChildA = { a: number } type ChildB = ChildA & { b: number } type ParentA = { children: ChildA[] } type ParentB = ParentA & { children: ChildB[] }
预期触发错误的场景1
直接初始化ParentB类型变量时,会触发TypeScript的类型错误:
const parentB1: ParentB = { children: [{ a: 1 }] }
错误提示:
Type '{ a: number; }' is not assignable to type 'ChildA & { b: number; }'.
Property 'b' is missing in type '{ a: number; }' but required in type '{ b: number; }'.
预期触发错误的场景2
直接操作ChildB[]类型的数组时,同样会触发预期的类型错误:
const children: ChildB[] = [] children.push({ a: 1 })
错误提示:
Argument of type '{ a: number; }' is not assignable to parameter of type 'ChildB'.
Property 'b' is missing in type '{ a: number; }' but required in type '{ b: number; }'.
未触发错误的异常场景
但下面这段代码却没有触发任何TypeScript错误:
const parentB2: ParentB = { children: [] } parentB2.children.push({ a: 1 }) // no error
问题原因
观察可知parentB2.children的类型是ChildA[] & ChildB[],TypeScript未报错的核心原因在于数组的交集类型特性:当两个数组类型取交集时,调用数组方法(如push)时,参数类型会被解析为两个数组元素类型的联合类型(即ChildA | ChildB),而{a:1}符合ChildA类型,因此不会触发错误。
解决方案
要规避这个行为并触发预期的类型错误,可以修改ParentB的定义,先从ParentA中省略children属性,再重新定义该属性:
type ParentB = Omit<ParentA, "children"> & { children: ChildB[] }
内容的提问来源于stack exchange,提问作者joshden

