TypeScript中如何通过继承接口对象填充基础接口对象对应属性
问题根因
- 第一版遍历赋值逻辑存在两处错误:
Array.prototype.forEach无返回值,将其执行结果赋值给a,实际会把a置为undefined- 初始
a对象仅初始化了必填属性a,可选属性x未在初始对象上定义,使用key in a做判断时,x会被判定为非a自有属性,不会触发赋值
- 类型断言方案无效的核心原因:TypeScript的类型检查仅在编译阶段生效,编译后所有类型信息会被完全擦除,
as A不会对实际对象做任何属性裁剪,本质是直接把ab的对象引用赋值给a,必然会携带AB接口独有的b属性。
实现方案
TypeScript接口在编译后会被完全擦除,运行时无法直接读取接口定义的属性列表,因此不存在纯靠类型系统自动完成属性裁剪的方案,必须显式维护父接口的合法属性清单做定向拷贝,参考实现如下:
interface A { a: string; x?: string } interface AB extends A { b: string } let a: A = { a : 'initial' } const ab: AB = { a: 'alex', b: 'bolbets', x: 'hello world!' }; // 维护A接口的所有合法属性列表,加keyof A类型约束避免写错属性名 const aValidKeys: (keyof A)[] = ['a', 'x']; a = aValidKeys.reduce((result, key) => { // 兼容可选属性在源对象上不存在的场景 if (Object.prototype.hasOwnProperty.call(ab, key)) { result[key] = ab[key]; } return result; }, {} as A); // 执行后a的值为 { a: 'alex', x: 'hello world!' },无多余的b属性
避坑提示:不要依赖
Object.keys(ab)遍历源对象做动态属性判断,没有运行时的属性清单作为依据,根本无法区分某个属性是父接口定义的还是子接口独有的,必然出现漏拷贝可选属性、多拷贝子接口独有属性的问题。
内容的提问来源于stack exchange,提问作者Alex Pappas
相关产品推荐
相关产品推荐

