如何为展开运算符解构得到的结果声明TypeScript类型
现有如下TypeScript代码:
type myType = { key1: string, optKey?: boolean, } const obj = { key1: 'hi', key2: 'yes', } const { key2, ...typedObj } = obj typedObj.optKey = true
执行类型检查时会抛出错误:Property 'optKey' does not exist on type '{ key1: string; }'。
目标是让TS识别typedObj为myType类型,支持在const解构声明阶段、或声明后完成类型指定,已知const typedObj2 = typedObj as myType的写法可生效,但需要引入额外临时变量,需要无临时变量的替代方案。
方案1:解构声明阶段直接做类型断言(最简洁,无额外变量)
在解构表达式的右侧对原对象做类型断言,指定其类型为myType交叉上被解构的key2属性类型即可,不需要引入任何临时变量:
const { key2, ...typedObj } = obj as myType & { key2: string }; typedObj.optKey = true; // 无类型报错
该写法的逻辑是:告知TS原对象obj同时包含myType的所有属性、以及额外的key2字符串属性,解构剔除key2后,剩余的typedObj会被自动推导为myType类型,直接访问、赋值可选属性optKey不会触发类型错误。
方案2:增加类型校验的安全写法(TS 4.9+支持)
如果担心直接用as强转跳过类型检查、导致原对象结构写错的隐患,可以搭配satisfies运算符先校验原对象的结构,再做类型断言:
const { key2, ...typedObj } = obj satisfies { key1: string; key2: string } as myType & { key2: string }; typedObj.optKey = true;
satisfies会先校验obj确实存在key1、key2两个字符串属性,校验通过后再执行类型断言,避免断言写错导致的类型隐患。
注意事项
不要尝试直接在解构左侧标注类型,如下写法会抛出类型错误:
// 错误写法 const { key2, ...typedObj }: { key2: string } & myType = obj;
TS会报错提示obj缺少optKey属性,因为左侧标注的类型要求整个对象符合myType结构,但原obj上并没有定义optKey(哪怕它是可选属性),因此必须在右侧做断言,告知TS解构后剩余的对象会被当作myType使用。
内容的提问来源于stack exchange,提问作者Igor Serebryany

