Imagine I have the following interface defined:
export interface BaseInterface {
foo?: Record<string, SomeType>;
bar?: Record<string, SomeOtherType>;
... // Many more fields like this
}
I want to create a new type, which will be equivalent to BaseInterface
, except all record types should be wrapped in Partial
like this:
export type MyType = {
foo?: Record<string, Partial<SomeType>>;
bar?: Record<string, Partial<SomeOtherType>>;
...
}
I don't want to manually write the new interface, because there are too many fields in the base interface there are multiple interfaces that I need to overwrite like this, so I would like to find out if there is a way to achieve the same result using some TypeScript magic.
CodePudding user response:
You can use a conditional type to extract the record value type and make that partial. We can then use a mapped type to apply to all properties:
type RecordValuePartial<T> = T extends Record<string, infer V>? Record<string, Partial<V>>: T
type AllRecordValuePartial<T> = {
[P in keyof T]: RecordValuePartial<T[P]>
}
export type MyType = AllRecordValuePartial<BaseInterface> // Same as:
// export type MyTypeManual = {
// foo?: Record<string, Partial<SomeType>> | undefined;
// bar?: Record<string, Partial<SomeOtherType>>| undefined ;
// }