Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 11x 11x 29x 29x 2x 2x 2x 5x 4x 5x 9x 9x 11x | import { castArray, invert } from 'lodash-uni' import { LiteralUnion, OneOrMore, ValueOf } from '../types' export type EnumKey = string export type EnumValue = string | number | boolean export type EnumMap = Record<EnumKey, EnumValue> // https://stackoverflow.com/questions/56415826/is-it-possible-to-precisely-type-invert-in-typescript type AllValues<T extends Record<EnumKey, EnumValue>> = { [P in keyof T]: { label: P value: T[P] extends true ? 'true' : T[P] extends false ? 'false' : T[P] } }[keyof T] type InvertResult<T extends Record<EnumKey, EnumValue>> = { // @ts-ignore [P in AllValues<T>['value']]: Extract<AllValues<T>, { value: P }>['label'] } type List<T extends Record<EnumKey, EnumValue>> = Array< { [P in keyof T]: { label: P value: T[P] } }[keyof T] > export type EnumResult<T extends EnumMap> = T & InvertResult<T> & { $list: List<T> $buildList: (keys: Array<keyof T> | Record<keyof T, any>) => List<T> $is(value: any, keys: OneOrMore<LiteralUnion<keyof T, ValueOf<T>>>): boolean } /** * 构造枚举数据。 * * @param map 枚举映射数据 */ export function makeEnum<T extends EnumMap>(map: T): EnumResult<T> { const res: EnumResult<T> = { ...map, ...invert(map), } as any Object.defineProperties(res, { $list: { value: Object.keys(map).reduce<EnumResult<T>['$list']>((res, key) => { res.push({ label: key, value: map[key] as any, }) return res }, [] as any), enumerable: false, writable: false, configurable: false, }, $buildList: { value: (keys => { const labelMap = Array.isArray(keys) ? undefined : keys keys = Array.isArray(keys) ? keys : Object.keys(keys) return Object.keys(map).reduce<ReturnType<EnumResult<T>['$buildList']>>( (res, key) => { if (keys.includes(key)) { res.push({ label: labelMap?.[key] || key, value: map[key] as any, }) } return res }, [] as any, ) as any }) as EnumResult<T>['$buildList'], enumerable: false, writable: false, configurable: false, }, $is: { value: ((value, keys) => { return castArray(keys).some( key => value === key || value === res[key as any], ) }) as EnumResult<T>['$is'], enumerable: false, writable: false, configurable: false, }, }) return res } |