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
}
|