Мне нужно принять пользовательский ввод и подтвердить, что значение является допустимым значением перечисления.Например, у меня есть enum:
enum Gender {
Male = 'MALE',
Female = 'FEMALE',
Neutral = 'NEUTRAL'
}
Пользователь может ввести туда любое значение, и я хотел бы утверждать, что это значение Gender
, если значение является действительным Gender
.
Было бы удобно иметь такую функцию:
function toEnum<T, E extends typeof T>(enumType: E, value: string): T | null {
if (Object.values(enumType).includes(value)) {
return value as T;
}
return null;
}
Который я мог бы назвать так:
const a: Gender = toEnum(Gender, 'FEMALE'); // === Gender.Female
const b: Gender = toEnum(Gender, 'APPLE'); // null;
Я действительно не знаю, что общегоподпись имеет смысл:
function toEnum<T, E extends typeof T>(enumType: E, value: string): T | null { /* ... */ }
function toEnum<T>(enumType: typeof T, value: string): T | null { /* ... */ }
function toEnum<E, T instanceof E>(enumType: E, value: string): T | null { /* ... */ }
Я знаю, что эти вещи не действительны.Я просто пытаюсь выразить свое намерение.
В любом случае, каков наименьший хакерский способ заставить машинописный текст выводить, что тип T будет значением перечисления при сохранении безопасности типов?Есть ли лучший способ написать безопасную для типов функцию обратного отображения для строковых перечислений?
EDIT:
Несколько дополнительных примеров, демонстрирующих то, чего я хотел бы достичь.Я хотел бы вывести тип T
, чтобы я мог устранить странное поведение, и я бы хотел избежать использования any
, чтобы поддерживать безопасность типов.
enum Gender {
Male = 'MALE',
Female = 'FEMALE',
Neutral = 'NEUTRAL'
}
type Maybe<T> = T | null;
export function toEnum<T>(enumType: any, value: string): Maybe<T> {
if (Object.values(enumType).includes(value)) {
return value as unknown as T;
}
return null;
}
const shouldBeFemale: Maybe<Gender> = toEnum<Gender>(Gender, 'FEMALE'); // Gender.Female
const shouldBeNull: Maybe<Gender> = toEnum<Gender>(Gender, 'NOT VALID'); // null
// but this is lame
enum Fruit {
Apple = 'APPLE',
Orange = 'ORANGE'
}
const wtfItIsApple: Maybe<Gender> = toEnum<Gender>(Fruit, 'APPLE'); // 'APPLE' . . . wat!?
const validButStillSilly: Maybe<Gender> = toEnum<Gender>(Fruit, 'NOT VALID'); // null
const ughAny: Maybe<Gender> = toEnum<Gender>(217, ':('); // null