TypeScript中条件对象成员未触发类型错误的原因及解决方法
代码示例
type Schema = { a: string; b?: string; } // 尽管会存在未类型化属性,但此处未报错 const schema1: Schema = { a: 'foo', ...(true ? {c: 'bar'} : undefined) } // 如预期般报错 const schema2: Schema = { a: 'foo', c: 'bar' }
问题
尽管Schema未定义c成员,但第一种情况并未触发类型错误,请解答:
- 这是否为预期行为?若是,原因是什么?
- 如何编写代码才能实现预期效果:当添加未类型化的条件对象成员时触发类型错误?
解答
1. 这是TypeScript的预期行为
TypeScript的多余属性检查仅对直接声明的对象字面量生效。当使用展开运算符(...)引入动态生成的对象(比如示例中的条件表达式结果)时,TypeScript会默认跳过多余属性校验——因为展开的对象可能是运行时动态生成的,编译阶段无法完全确定其结构,所以不会强制校验其属性是否完全匹配目标类型。而schema2是直接写出的对象字面量,属于静态可分析的结构,因此触发了多余属性检查并报错。
2. 实现严格校验的几种方法
方法一:使用工具函数约束展开对象的类型
定义一个工具函数,强制展开的对象只能包含Schema允许的属性:
type Schema = { a: string; b?: string; } const restrictToSchema = <T extends Partial<Schema>>(obj: T) => obj; // 此时会触发类型错误,因为{c: 'bar'}不符合Partial<Schema> const schema1: Schema = { a: 'foo', ...restrictToSchema(true ? {c: 'bar'} : undefined) }
方法二:使用Object.assign替代展开运算符
Object.assign的类型检查会严格校验所有参数的属性是否匹配目标类型:
type Schema = { a: string; b?: string; } // 此时会触发类型错误 const schema1: Schema = Object.assign({a: 'foo'}, true ? {c: 'bar'} : undefined);
方法三:使用satisfies运算符(TypeScript 4.9+)
satisfies会严格检查对象是否符合目标类型,包括多余属性:
type Schema = { a: string; b?: string; } // 此时会触发类型错误 const schema1 = { a: 'foo', ...(true ? {c: 'bar'} : undefined) } satisfies Schema;
内容的提问来源于stack exchange,提问作者Dimitris Karagiannis
相关产品推荐
相关产品推荐

