Last active
February 24, 2021 16:19
-
-
Save sgoguen/abfb62e2571dc8ca4ca30be84475e04c to your computer and use it in GitHub Desktop.
Using TypeScript's Mapped Types and Index Types to extract message types from an interface
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
| // Given an interface like this, I can have TypeScript automatically | |
| // generate message types from all of the "update" methods below. | |
| export interface Person { | |
| // We'll ignore these properties | |
| name: string; | |
| age: number; | |
| dob: Date; | |
| // We'll ignore any method that returns void (We want methods to return new methods) | |
| setDate(newDate: Date): void; | |
| // Methods accepting simple types are ok | |
| setName(newName: string): Person; | |
| setAge(newAge: number): Person; | |
| // But we'll ignore methods with more than one argument for now | |
| setBoth(newName: string, newAge: number): Person; | |
| // A method accepting a record is good | |
| setBothObj(r: { newName: string, newAge: number }): Person; | |
| } | |
| /* | |
| Given our Person type, we want to extract a union type. | |
| type PersonUpdateMessage = { | |
| type: "setName"; | |
| payload: string; | |
| } | { | |
| type: "setBothObj"; | |
| payload: { | |
| newName: string; | |
| newAge: number; | |
| }; | |
| } | { | |
| type: "setAge"; | |
| payload: number; | |
| } | |
| */ | |
| // We'll use mapped types to extract the key name and payload type. | |
| // Then we'll use index types at the end to create our union type. | |
| export type UpdateMessages<T> = { | |
| [K in keyof T]: T[K] extends ((x: infer P) => T) ? { type: K, payload: P } : never | |
| }[keyof T]; | |
| // Intellisense shows your new update message types | |
| export type PersonUpdateMessage = UpdateMessages<Person>; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment