Функция Typescript для преобразования члена перечисления строки в перечисление
Я хотел бы написать что-то вроде этого в Typescript:
export function stringToEnum<T>(enumObj: T, str: string): keyof T {
return enumObj[str];
}
и используйте его следующим образом:
enum MyEnum {
Foo
}
stringToEnum<MyEnum>(MyEnum, 'Foo');
куда бы он вернулся
MyEnum.Foo
Вышеприведенная функция работает, как и ожидалось... но при наборе ошибок возникают ошибки. Для параметра MyEnum
в stringToEnum<MyEnum>(MyEnum, 'Foo');
Машинопись жалуется, что:
Аргумент типа 'typeof MyEnum' не может быть назначен параметру типа 'MyEnum'
что имеет смысл... к сожалению. Любые идеи о том, как я могу обойти это?
3 ответа
Вы можете сделать все это без необходимости писать функцию:
enum Color {
red,
green,
blue
}
// Enum to string
const redString: string = Color[Color.red];
alert(redString);
// String to enum
const str = 'red';
const redEnum: Color = Color[str];
alert(redEnum);
Или вы можете повеселиться с ним...
enum MyEnum {
Foo,
Bar
}
function stringToEnum<ET, T>(enumObj: ET, str: keyof ET): T{
return enumObj[<string>str];
}
const val = stringToEnum<typeof MyEnum, MyEnum>(MyEnum, 'Foo');
// Detects that `foo` is a typo
const val2 = stringToEnum<typeof MyEnum, MyEnum>(MyEnum, 'foo');
Ваша подпись немного перепутана. Тип возврата должен быть T[keyof T]
если вы намерены для метода вернуть значение перечисления. Тип str
параметр также должен быть keyof T
чтобы вы не могли передавать недопустимые строки, но это ограничит вас передачей строковых литералов в (или типизированные переменные типа keyof T
, но нет string
):
function stringToEnum<T>(enumObj: T, str: keyof T): T[keyof T]
Тогда либо не указывайте param типа, и пусть компилятор правильно выводит тип:
// type: Foo
// value: 0
const result = stringToEnum(MyEnum, 'Foo');
Или вам нужно предоставить typeof MyEnum
в качестве параметра типа:
// type: Foo
// value: 0
const result = stringToEnum<typeof MyEnum>(MyEnum, 'Foo');
Если вы действительно хотите иметь возможность передавать любое произвольное строковое имя перечисления, тогда возвращаемый тип - ложь: должно быть T[keyof T] | undefined
, Вы также столкнетесь с проблемами при попытке enumObj[str]
если тип str
является string
и у тебя есть noImplicitAny
опция компилятора включена.
Есть еще кое-что для создания универсальных функций, которые правильно работают с типами перечислений, особенно числовых перечислений, которые имеют записи обратного просмотра во время выполнения. Посмотрите на исходный код ts-enum-util
( github, npm) для вдохновения
stringToEnum(MyEnum, 'Foo');
Просто оставьте общий и пусть машинопись делает это. Это потому, что тип, хранящийся в MyEnum, не соответствует самому Enum, но является типом объединения его значений:
enum Test { A, B };
const value: Test /* "A" | "B" */ = Test.A;