typescript 如何删除接口中嵌套对象的属性?

ztyzrc3y  于 2023-01-27  发布在  TypeScript
关注(0)|答案(2)|浏览(264)

给定以下示例

interface DataProvider {
    type: string;
    // other props
}

interface ApiConfiguration {
    dataProvider: DataProvider;
    // other props
}

interface Configuration {
    api: ApiConfiguration;
    // other props
}

const configuration: Configuration = {
    api: {
        dataProvider: { type: 'http' }
    }
};

将根据架构验证此配置。对于给定的测试,我希望确保在缺少type字段时将引发验证错误。

delete configuration.api.dataProvider.type

是不可能的,因为
“delete”运算符的操作数必须是可选的。
因为接口必须有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;

但是有没有更优雅的方法从嵌套的子对象中移除 prop 呢?

cygmwpex

cygmwpex1#

可以使用小型实用工具省略嵌套类型中的type属性。

type ChangeFields<T, R> = Omit<T, keyof R> & R;

type TestConfig = ChangeFields<Configuration, {
    api: ChangeFields<ApiConfiguration, {
        dataProvider: ChangeFields<DataProvider, {
            type?: string
        }>
    }>
}>

const withoutType = (obj: Configuration): TestConfig  => {
    const res = obj as TestConfig; //deepclone if used elsewhere
    delete res.api.dataProvider.type;
    return res;
}

const c = withoutType(configuration);

因为你只需要写一个测试就可以了,所以这可能不是问题,但是当你删除一个嵌套属性时,如果它在其他地方被引用了,你应该正确地深度克隆这个对象,否则你会通过引用修改一个不同类型的对象。

gjmwrych

gjmwrych2#

你可以使用Typescript中的as关键字来完成这个任务,当你使用它的时候,你明确地告诉Typescript不要担心对象内部的内容。
有关详细信息,请参见this question

interface DataProvider {
    type: string;
    // other props
}

interface ApiConfiguration {
    dataProvider: DataProvider;
    // other props
}

interface Configuration {
    api: ApiConfiguration;
    // other props
}

const configuration: Configuration = {
    api: {
        dataProvider: {} as DataProvider,
    }
};

相关问题