Home > Net >  Generic that modifies a type's property
Generic that modifies a type's property

Time:11-27

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;

Playground


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;

Playground


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 }

Playground

  • Related