Home > Net >  How to delete property from nested objects inside interface?
How to delete property from nested objects inside interface?

Time:01-25

Given the following sample

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' }
    }
};

This configuration will be validated against a schema. For a given test I want to ensure a validation error will be thrown if the type field is missing.

delete configuration.api.dataProvider.type

is not possible because

The operand of a 'delete' operator must be optional.

since the interface must have the type prop. I am aware that there are Pick and Omit, but creating a custom interface type for each test case would be very time-consuming.

Currently I'm using this approach

// 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;

but is there a more elegant way to remove props from nested children?

CodePudding user response:

You can use a small utility to omit the type property in your nested type.

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

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

const withoutType = (obj: Configuration): Config  => {
    const res = { ...obj } as Config;
    delete res.api.dataProvider.type;
    return res;
}

const c = withoutType(configuration);

CodePudding user response:

You can use the as keyword from Typescript to do this. When using it, you explicitly tell Typescript not to worry about what's inside the object.

See this question for details.

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,
    }
};
  • Related