Last active
July 4, 2020 22:14
-
-
Save mceachen/b6f2537324da36d0919e2fd4b9cbed8e to your computer and use it in GitHub Desktop.
TypeScript enumerations
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 const Directions = strEnum("North", "South", "East", "West") | |
export type Direction = StrEnumKeys<typeof Directions> |
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
// Generally useful types: | |
export type Maybe<T> = T | undefined | |
export type MaybeNull<T> = Maybe<T> | null | void | |
// See https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html | |
export type StrEnumType<T extends string> = { | |
[K in T]: K | |
} | |
export type StrEnumHelpers<T extends string> = { | |
values: T[] | |
length: number | |
has(s: MaybeNull<string>): s is T | |
indexOf(s: MaybeNull<string>): number | |
validOrElse<R>(s: MaybeNull<string>, defaultValue: () => R): T | R | |
map<R>(s: MaybeNull<string>, f: (t: T) => R): Maybe<R> | |
} | |
export type StrEnum<T extends string> = StrEnumType<T> & StrEnumHelpers<T> | |
export type StrEnumKeys<Type> = Type extends StrEnum<infer X> ? X : never | |
export function strEnum<T extends string>(...o: T[]): StrEnum<T> { | |
const values = Object.freeze(o) as T[] | |
const dict: StrEnumType<T> = {} as any | |
for (const ea of values) { | |
dict[ea] = ea | |
} | |
const has = (s: MaybeNull<string>): s is T => | |
s != null && values.includes(s as T) | |
const indexOf = (s: MaybeNull<string>) => | |
s == null ? -1 : values.indexOf(s as T) | |
const validOrElse = <R>(s: MaybeNull<string>, defaultValue: () => R) => | |
has(s) ? s : defaultValue() | |
const map = <R>(s: string, f: (t: T) => R) => (has(s) ? f(s as T) : undefined) | |
return { | |
...dict, | |
values, | |
length: values.length, | |
has, | |
indexOf, | |
validOrElse, | |
map | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment