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