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

RMAG news

MappingByDiscriminator

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 ?
{
[d in GetPropertyType<E, D>]: UnionMemberByDiscriminator<E, D, d>[];
}
: never;

Will map types in a union by a discriminator.
Example:

type Car = {
kind: car,

};

type Truck = {
kind: truck,

};

type Vehicle = Car | Truck;

Then

type VehiclesByKind = MappingByDiscriminator<Vehicle,kind>;

Will produce :

type VehiclesByKind = {
car: Car[],
truck: Truck[],
}

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;

Example:

type Entity = {
kind: human | animal,
size: microscopic | small | big | giant,
}

Then

type SizeType = GetProperty<Entity,size>

Will produce

type SizeType = microscopic | small | big | giant;

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
> = E extends {[key in D]:DValue} ? E : never;

Example:

type Car = {
kind: car,

};

type Truck = {
kind: truck,

};

type Vehicle = Car | Truck;

type InferredCar =
UnionMemberByDiscriminator<Vehicle, kind, car>

Will produce

type InferredCar = Car;

This is useful in a generic context (see above)

Leave a Reply

Your email address will not be published. Required fields are marked *