TypeScript嵌套解构赋值加默认值报错原因及相关疑问
问题场景
在TypeScript中使用嵌套解构赋值并设置默认值时出现报错,原始代码如下:
interface TaskListItemType { id: number; } type PageType = { current?: number; size?: number; total?: number; } declare const data:{ records: TaskListItemType[]; page: PageType; } | undefined const { records, page: { total, current, size } = {} } = data|| {};
报错信息:Initializer provides no value for this binding element and the binding element has no default value
我原以为报错原因是{}不包含对应属性,于是添加类型断言{} as PageType后代码可正常运行,修改后的代码:
const { records, page: { total, current, size } = {} as PageType } = data|| {};
但这里有个疑惑:如果报错原因确实是{}缺少对应属性,为什么以下非嵌套的解构代码不会报错?
interface TaskListItemType { id: number; } type PageType = { current?: number; size?: number; total?: number; } declare const data:{ records: TaskListItemType[]; page: PageType; } | undefined const { records, page } = data|| {};
核心原因与解答
1. 非嵌套解构不报错的逻辑
当执行const { records, page } = data || {}时,data || {}的类型被推断为{ records: TaskListItemType[]; page: PageType; } | {}。此时page的类型会被自动推断为PageType | undefined——因为空对象{}中没有page属性,TypeScript允许这种情况,而PageType本身的所有属性都是可选的,完全符合类型规则,所以不会报错。
2. 嵌套解构报错的本质
在嵌套解构page: { total, current, size } = {}中,默认值{}的类型被TypeScript推断为纯空对象类型{},而非PageType。此时你要从空对象中解构total、current、size,但这些属性在{}类型中完全不存在,且你没有给这三个变量单独设置默认值,TypeScript判定这些变量无法获取有效值,因此抛出报错。
3. 类型断言生效的原因
当把默认值改为{} as PageType时,相当于告诉TypeScript这个空对象属于PageType类型。由于PageType的所有属性都是可选的,TypeScript会将total、current、size的类型推断为number | undefined——可选属性允许不存在,解构时会自动赋值为undefined,因此不再报错。
4. 更规范的替代方案
除了类型断言,还有两种更优雅的写法:
给每个嵌套属性单独设置默认值:
const { records, page: { total = 0, current = 1, size = 10 } = {} } = data || {};即使
page为空对象或undefined,每个变量都有明确的默认值,类型检查直接通过。给
page设置符合PageType的完整默认对象:const { records, page: { total, current, size } = { current: 1, size: 10, total: 0 } } = data || {};明确提供符合类型结构的默认值,无需额外断言即可通过检查。
内容的提问来源于stack exchange,提问作者myNameIsDu

