TypeScript中如何从接口嵌套对象中删除必填属性?
问题描述
示例代码:
interface DataProvider { type: string; // 其他属性 } interface ApiConfiguration { dataProvider: DataProvider; // 其他属性 } interface Configuration { api: ApiConfiguration; // 其他属性 } const configuration: Configuration = { api: { dataProvider: { type: 'http' } } };
这段配置会依据Schema进行校验。在某个测试场景中,需要验证当type字段缺失时会抛出校验错误。
直接执行以下代码无法实现需求:
delete configuration.api.dataProvider.type
会抛出如下错误:
The operand of a 'delete' operator must be optional.
原因是接口定义中type为必填属性。虽然可以用Pick和Omit工具类型,但为每个测试用例自定义接口类型太耗时。
当前采用的实现方式如下:
// eslint-disable-next-line @typescript-eslint/no-explicit-any const clonedConfiguration: any = structuredClone(configuration); // eslint-disable-next-line @typescript-eslint/no-unused-vars const {type: _, ...dataProviderWithoutType} = clonedConfiguration.api.dataProvider; clonedConfiguration.api.dataProvider = dataProviderWithoutType;
请问是否存在更优雅的方式来删除嵌套子对象中的属性?
可选优雅解法
方式一:类型断言快速绕过TS检查(测试场景适用)
测试环境不需要严格类型约束,直接用类型断言将目标对象转为any,即可执行删除操作:
const clonedConfig = structuredClone(configuration); delete (clonedConfig.api.dataProvider as any).type;
代码简洁,无需额外解构,适合测试场景快速修改配置。
方式二:封装通用工具函数复用逻辑
如果需要多次处理类似嵌套属性删除场景,可以封装通用函数:
function deleteNestedProperty<T>(obj: T, path: string[]): T { const cloned = structuredClone(obj); let current: any = cloned; // 遍历到目标属性的父级对象 for (let i = 0; i < path.length - 1; i++) { current = current[path[i]]; } delete current[path[path.length - 1]]; return cloned; } // 使用示例 const configWithoutType = deleteNestedProperty(configuration, ['api', 'dataProvider', 'type']);
一次封装可复用在各种嵌套场景,提升代码可维护性。
方式三:嵌套解构生成新对象(类型更安全)
通过嵌套解构直接生成排除目标属性的新对象,无需禁用ESLint规则:
const configWithoutType = { ...configuration, api: { ...configuration.api, dataProvider: { // 用Omit临时调整类型,解构时排除type ...(configuration.api.dataProvider as Omit<DataProvider, 'type'>) } } };
保留类型检查的同时完成属性删除,适合对类型安全有要求的场景。
内容的提问来源于stack exchange,提问作者baitendbidz
相关产品推荐
相关产品推荐

