In TypeScript (4.5.2), I'm trying to create a generic that takes a type and modifies some of its properties.
type StrictNumber = {
doesNotChange: string,
nullable: false,
value: number,
};
type MakeNullable<T extends { nullable: false, value: unknown }> = {
[Property in keyof T]: Property extends 'nullable'
? true
: Property extends 'value'
? T[Property] | null
: T[Property]
};
type NullableNumber = MakeNullable<StrictNumber>;
Here's the resulting type for NullableNumber
:
type NullableNumber = {
doesNotChange: string,
nullable: true,
value: number | null,
};
Which is exactly what I want. However the MakeNullable
generic is really not an elegant solution, it's very verbose. It would be even more if I added more properties to modify.
CodePudding user response:
You could infer the value
type using conditional type:
type MakeNullable<T extends { nullable: false, value: unknown }> = T extends { value: infer V }
? { nullable: true, value: V | null } : never;
If you want to carry over all additional properties, you can make an intersection with original type, but omitting the modified properties:
type MakeNullable<T extends { nullable: false, value: unknown }> = T extends { value: infer V }
? Omit<T, 'nullable' | 'value'> & { nullable: true, value: V | null } : never;
Or even simpler (adjusted @captain-yossarian suggestion):
type MakeNullable<T extends { nullable: false, value: unknown }> =
Omit<T, 'nullable' | 'value'> & { nullable: true, value: T['value'] | null }