TypeScript中如何让类实例自动访问其子对象属性?
解决方案
针对你的需求,不需要复制属性,有几种更优雅的实现方式,可根据属性数量选择:
1. 使用ES6 Proxy(推荐多属性场景)
Proxy能自动拦截所有属性的访问和修改,把对FolderImpl实例的操作转发到内部的folder属性上,无需手动为每个属性写重复代码。
代码示例:
interface FolderInterface { name: string; source: { type: 'usb' }; // 其他更多属性 } class FolderImpl { folder: FolderInterface; constructor(folder: FolderInterface) { this.folder = folder; // 返回代理实例,拦截属性访问 return new Proxy(this, { get(target, prop) { // 优先返回实例自身的属性 if (prop in target) { return Reflect.get(target, prop); } // 否则转发到内部的folder对象 return Reflect.get(target.folder, prop); }, // 支持属性修改(可选) set(target, prop, value) { if (prop in target) { return Reflect.set(target, prop, value); } return Reflect.set(target.folder, prop, value); } }); } } // 使用示例 const usbFolder: FolderInterface = { name: "我的USB文件夹", source: { type: 'usb' } }; const folderImpl = new FolderImpl(usbFolder); console.log(folderImpl.name); // 输出 "我的USB文件夹" console.log(folderImpl.source); // 输出 { type: 'usb' } folderImpl.name = "更新后的文件夹名"; console.log(folderImpl.folder.name); // 输出 "更新后的文件夹名"
2. 手动定义Getter/Setter(适合少量属性)
如果需要暴露的属性不多,可以直接为每个属性定义getter(和setter,若需要修改),直接返回内部folder的对应属性,类型提示更直接:
interface FolderInterface { name: string; source: { type: 'usb' }; // 其他更多属性 } class FolderImpl { folder: FolderInterface; constructor(folder: FolderInterface) { this.folder = folder; } // 为name属性定义访问器 get name() { return this.folder.name; } set name(value: string) { this.folder.name = value; } // 同理处理source属性 get source() { return this.folder.source; } } // 使用示例 const usbFolder: FolderInterface = { name: "我的USB文件夹", source: { type: 'usb' } }; const folderImpl = new FolderImpl(usbFolder); console.log(folderImpl.name); // 输出 "我的USB文件夹"
3. 让类实现接口并委托
让FolderImpl实现FolderInterface,确保类型检查的同时,通过访问器委托到内部的folder对象,本质和方法2类似,但能获得完整的接口类型约束:
interface FolderInterface { name: string; source: { type: 'usb' }; // 其他更多属性 } class FolderImpl implements FolderInterface { folder: FolderInterface; constructor(folder: FolderInterface) { this.folder = folder; } get name(): string { return this.folder.name; } set name(value: string) { this.folder.name = value; } get source(): { type: 'usb' } { return this.folder.source; } }
方法对比
- Proxy:无需维护每个属性,新增属性自动生效,适合属性多的场景,现代环境兼容性没问题。
- 手动Getter:代码更直观,性能略优,但属性多的时候会有大量重复代码。
内容的提问来源于stack exchange,提问作者AshD
相关产品推荐
相关产品推荐

