DEV Community

Frédéric Leroy
Frédéric Leroy

Posted on

Typescript type grouping a union type of objects by any property discriminating these objects.

MappingByDiscriminator

Example:

type Car = {
  kind: "car",
  ...
};

type Truck = {
  kind: "truck",
  ...
};

type Vehicle = Car | Truck;
Enter fullscreen mode Exit fullscreen mode

Then

type VehiclesByKind = MappingByDiscriminator<Vehicle,"kind">;
Enter fullscreen mode Exit fullscreen mode

Will produce :

type VehiclesByKind = {
    car: Car[],
    truck: Truck[],
}
Enter fullscreen mode Exit fullscreen mode

Mapping union type on discriminator
using the UnionMemberByDiscriminator and GetProperty described below,

type MappingByDiscriminator< E extends object, D extends keyof E > = 
   GetPropertyType<E,D> extends string | number ?
   {
      [d in GetPropertyType<E, D>]: UnionMemberByDiscriminator<E, D, d>[];
    }
  : never;
Enter fullscreen mode Exit fullscreen mode

Will map types in a union by a discriminator.

GetProperty

Get the type of an object property with generics

type GetProperty<E extends object, P extends keyof E> = 
  E extends { [key in P]: infer V } ? V : never;
Enter fullscreen mode Exit fullscreen mode

Example:

type Entity = {
   kind: 'human' | 'animal',
   size: 'microscopic' | 'small' | 'big' | 'giant',
}
Enter fullscreen mode Exit fullscreen mode

Then

type SizeType = GetProperty<Entity,"size">
Enter fullscreen mode Exit fullscreen mode

Will produce

type SizeType = 'microscopic' | 'small' | 'big' | 'giant';
Enter fullscreen mode Exit fullscreen mode

UnionMemberByDiscriminator

Extract a specific type from a union for a given discriminator value (can be used with generics)

type UnionMemberByDiscriminator<
  E extends object,
  D extends keyof E,
  DValue extends string | number
> = E extends {[key in D]:DValue} ? E : never;
Enter fullscreen mode Exit fullscreen mode

Example:

type Car = {
  kind: "car",
  ...
};

type Truck = {
  kind: "truck",
  ...
};

type Vehicle = Car | Truck;

type InferredCar = 
   UnionMemberByDiscriminator<Vehicle, "kind", "car">
Enter fullscreen mode Exit fullscreen mode

Will produce

type InferredCar = Car;
Enter fullscreen mode Exit fullscreen mode

This is useful in a generic context (see above)

Top comments (2)

Collapse
 
loriel_alade_f298650d4f69 profile image
Loriel Alade • • Edited

Just as a well-organized cheat sheet helps readers quickly compare and understand technical concepts, a clear product comparison can make purchasing decisions much easier. For truck owners researching retractable bed covers, Roll-N-Lock provides a useful comparison of the A-Series and M-Series, highlighting differences in construction, features, security, weather protection, and overall value.

Collapse
 
alex_ander_1bcc72456032a7 profile image
Alex Ander • • Edited

The TypeScript cheat sheet provides a practical quick-reference approach to programming concepts, making it useful for readers who appreciate clear, organized information and efficient solutions. In a similar spirit of choosing purpose-built solutions for everyday needs, BakFlip offers hard-folding truck bed covers designed around protection, functionality, and convenient access. For truck owners researching practical ways to keep their cargo covered while maintaining bed usability, the BakFlip MX4 for the Ford Maverick is worth exploring as a dedicated fit.