Files
privacy.sexy/src/application/Common/Enum.ts
undergroundwires 00d8e551db refactor extra code, duplicates, complexity
- refactor array equality check and add tests
- remove OperatingSystem.Unknown causing extra logic, return undefined instead
- refactor enum validation to share same logic
- refactor scripting language factories to share same logic
- refactor too many args in runCodeAsync
- refactor ScriptCode constructor to reduce complexity
- fix writing useless write to member object since another property write always override it
2021-04-11 14:37:02 +01:00

55 lines
2.1 KiB
TypeScript

// Because we cannot do "T extends enum" 😞 https://github.com/microsoft/TypeScript/issues/30611
export type EnumType = number | string;
export type EnumVariable<T extends EnumType, TEnumValue extends EnumType> = { [key in T]: TEnumValue };
export interface IEnumParser<TEnum> {
parseEnum(value: string, propertyName: string): TEnum;
}
export function createEnumParser<T extends EnumType, TEnumValue extends EnumType>(
enumVariable: EnumVariable<T, TEnumValue>): IEnumParser<TEnumValue> {
return {
parseEnum: (value, propertyName) => parseEnumValue(value, propertyName, enumVariable),
};
}
function parseEnumValue<T extends EnumType, TEnumValue extends EnumType>(
value: string,
enumName: string,
enumVariable: EnumVariable<T, TEnumValue>): TEnumValue {
if (!value) {
throw new Error(`undefined ${enumName}`);
}
if (typeof value !== 'string') {
throw new Error(`unexpected type of ${enumName}: "${typeof value}"`);
}
const casedValue = getEnumNames(enumVariable)
.find((enumValue) => enumValue.toLowerCase() === value.toLowerCase());
if (!casedValue) {
throw new Error(`unknown ${enumName}: "${value}"`);
}
return enumVariable[casedValue as keyof typeof enumVariable];
}
export function getEnumNames<T extends EnumType, TEnumValue extends EnumType>(
enumVariable: EnumVariable<T, TEnumValue>): string[] {
return Object
.values(enumVariable)
.filter((enumMember) => typeof enumMember === 'string') as string[];
}
export function getEnumValues<T extends EnumType, TEnumValue extends EnumType>(
enumVariable: EnumVariable<T, TEnumValue>): TEnumValue[] {
return getEnumNames(enumVariable)
.map((level) => enumVariable[level]) as TEnumValue[];
}
export function assertInRange<T extends EnumType, TEnumValue extends EnumType>(
value: TEnumValue,
enumVariable: EnumVariable<T, TEnumValue>) {
if (value === undefined) {
throw new Error('undefined enum value');
}
if (!(value in enumVariable)) {
throw new RangeError(`enum value "${value}" is out of range`);
}
}