Last active
May 27, 2021 00:07
-
-
Save tylerbrostrom/0672a9b1bbe932604cbc31158d6040c1 to your computer and use it in GitHub Desktop.
TypeScript Utility for Creating Discriminating Unions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| Create a discriminating union type from two or more object types. | |
| Why?: | |
| - Saves you a few keystrokes. | |
| - Esp. helpful for distinguishing between type aliases you don’t own. | |
| Caveats: | |
| - Discriminator property might clobber an existing property. | |
| Type Params: | |
| - `TMembers` - Union of tuples where `TMembers[0]` is the object type and `TMembers[1]` is the string value for the discriminator property. | |
| - `TDiscriminator` (optional) - Name of the discriminator property. Defaults to `'kind'`. | |
| @example | |
| ``` | |
| import type {Square, Circle} from 'some-library'; | |
| // type Circle = { | |
| // radius: number; | |
| // } | |
| // type Square = { | |
| // length: number | |
| // } | |
| type Shape = DiscriminatingUnion<[Circle, 'circle'] | [Square, 'square']>; | |
| // type Shape = | |
| // | { | |
| // kind: 'circle'; | |
| // radius: number; | |
| // } | |
| // | { | |
| // kind: 'square'; | |
| // length: number; | |
| // } | |
| // Profit! | |
| function area(shape: Shape): number { | |
| if (shape.kind === 'circle') { | |
| return Math.PI * shape.radius ** 2; | |
| } else if (shape.kind === 'square') { | |
| return shape.length ** 2; | |
| } | |
| } | |
| ``` | |
| */ | |
| type DiscriminatingUnion<TMembers, TDiscriminator extends string = 'kind'> = TMembers extends [ | |
| member: Record<string, any>, | |
| kind: string | |
| ] | |
| ? TMembers[0] & { [K in TDiscriminator]: TMembers[1] } | |
| : never; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment