-
-
Save renoirb/d30e7edbe32d9c6b9c2006b13db7a016 to your computer and use it in GitHub Desktop.
TypeScript type Discriminator factory
This file contains 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
export enum EmployeeRole { | |
DEVELOPER = 100, | |
PRODUCT_MANAGER = 200, | |
PRODUCT_DESIGNER = 300, | |
} | |
/** | |
* This is equivalent to: | |
* | |
* type EmployeeRoleType = 'SOFTWARE_DEVELOPER' | 'SOFTWARE_DEVELOPER_COOP'; | |
*/ | |
export type EmployeeRoleKeys = keyof typeof EmployeeRole; | |
/** | |
* Should we want to make sure we have a label for EVERY EmployeeRole | |
* | |
* Bookmarks: | |
* - https://stackoverflow.com/a/51832623 | |
*/ | |
export type EmployeeRoleMustHave<T> = { | |
[K in EmployeeRoleKeys]: Extract<K, EmployeeRoleKeys> extends never ? never : T; | |
}; | |
/** | |
* Translation label hash-map for Employee Roles. | |
* So we can display text instead of a number. | |
*/ | |
const ROLES: EmployeeRoleMustHave<string> = { | |
DEVELOPER: 'Software Developer', | |
PRODUCT_MANAGER: 'Product Manager', | |
PRODUCT_DESIGNER: 'Product Designer', | |
}; | |
/** | |
* Build up all possible role labels. | |
* This is here to help be re-used elsewhere, from both Express and Angular. | |
* That's also why we're enforcing above the ROLES map to make sure we don't miss. | |
*/ | |
const ownSubset = Object.entries(EmployeeRole).filter(i => 1 in i && typeof i[1] === 'number') as [string, number][]; | |
const rolesLabels = ownSubset.map(i => ([i[1], ROLES[i[0]]])) as [number, string][]; | |
// Return only a copy when called. Just to be sure we do not mutate. | |
export const EmployeeRolesLabelMap = (() => new Map<number, string>(rolesLabels))(); | |
export interface Employee { | |
role: EmployeeRole; | |
} | |
/** | |
* Runtime Typing utility. | |
* | |
* Take an HashMap object, extract keys, | |
* and possibly make it a type | |
*/ | |
export const convertRecordToDiscriminator = <T>( | |
hashMap: T, | |
): ReadonlyArray<keyof T> => { | |
const k = Object.keys(hashMap) as (keyof T)[]; | |
return Object.freeze(k); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There has been other attempts but were getting bigger and bigger