Mam takie is
enum Test {
'type1',
'type2',
'type3',
'type4',
'type5'
}
function getType(num: number) {
}
To czego chcę to jeśli num = 1
, zwróć type1
, jeśli num = 2
, zwróć type2
, jeśli num >= 5
, zwróć type5
.
Jak mogę to zrobić w getType
?
2 odpowiedzi
Wyliczenia TypeScript są dostępne, mimo że istnieje indeks numeryczny w czasie wykonywania, więc
return Test[1];
Zwróci indeks 1
z wyliczenia Test
.
Ponieważ chcesz, aby 1
zwrócił type1
, musimy odjąć 1 od Twojego num
, aby uzyskać żądany indeks:
enum Test {
'type1',
'type2',
'type3',
'type4',
'type5'
}
function getType(num: number) {
return Test[num - 1];
}
console.log(getType(1));
Wyświetli:
type1
Wypróbuj online!
Test
type5
. Chyba powinienem zrobić if(num >= 5) return Test[5] ?
return Test[num - 1] || Test[4]
, aby upewnić się, że istnieje. Proszę zobaczyć w akcji za pomocą to Online demo.
To trudne pytanie. Zobacz powiązane pytanie i moje artykuł.
Reprezentacja enum w czasie wykonywania jest obiektem dwukierunkowym.
const Test = {
0: "type1",
1: "type2",
2: "type3",
3: "type4",
4: "type5",
type1: 0,
type2: 1,
type3: 2,
type4: 3,
type5: 4,
}
Proszę o tym pamiętać podczas czytania.
Rozważ ten przykład:
enum MyEnum {
ONE, // 0
TWO // 1
}
// This utility type reverses object.
// All keys become values an all values become keys
type ReverseObj<T extends Record<string, string | number>> = {
[Prop in keyof T as T[Prop]]: Prop
}
{
type _ = ReverseObj<{ age: 42 }> // { 42: "age" }
}
// Type representation of runtime enum value
// Please keep in mind that enum runtime value is bidirectional
// this is why I have used ReverseObject
type EnumToObj = Pick<
{
[Prop in keyof typeof MyEnum]: `${typeof MyEnum[Prop]}`
}, keyof typeof MyEnum
>
type IsKeyValid<
InitialValue extends number,
> =
`${InitialValue}` extends keyof ReverseObj<EnumToObj>
? InitialValue
: never
{
type _ = IsKeyValid<1> // 1
type __ = IsKeyValid<2> // never
}
function handleEnum<
Index extends number,
>(index: IsKeyValid<Index>): `${Index}` extends keyof ReverseObj<EnumToObj> ? ReverseObj<EnumToObj>[`${Index}`] : never
function handleEnum<
Index extends number,
>(index: IsKeyValid<Index>) {
return MyEnum[index]
}
handleEnum(0) // "ONE"
handleEnum(1) // "TWO"
handleEnum(2) // expected error
handleEnum('ONE') // expected error
handleEnum(0.1) // expected error
handleEnum(NaN) // expected error
handleEnum(Infinity) // expected error
Pewne wyjaśnienie znajdziesz w komentarzach. Celem jest uczynienie nielegalnego państwa niereprezentacyjnym.
IsKeyValid
- zapewnia, że nie możesz dostarczać kluczy, które nie istnieją w enum. Na przykład nie możesz zadzwonić do handleEnum(10)
, ponieważ mamy tylko dwa klucze, stąd dozwolone klucze to 0 | 1
. Jeśli chodzi o wartość zwracaną, uzyskałem ją z odwróconego obiektu ReverseObj
.
Coś, o czym powinieneś wiedzieć:
- Typy
typeof MyEnum
iMyEnum
nie są równe. - Więcej wyjaśnień na temat używania
as
w[Prop in keyof T as T[Prop]]: Prop
znajdziesz tutaj - Warto użyć prostej krotki zamiast enum, jeśli nie używasz niestandardowych początkowych indeksów dla enum. Rozważ ten przykład:
const TUPLE = ['one', 'two', 'three'] as const;
type Tuple = typeof TUPLE
type AllowedIndex<Index extends number> = `${Index}` extends Exclude<keyof Tuple, keyof ReadonlyArray<any>> ? Index : never
const getter = <Index extends number>(index: AllowedIndex<Index>) =>
TUPLE[index]
getter(1) // ok, returns "two"
getter(23) // expected error
- W większości przypadków nawet lepiej jest użyć immutable object zamiast enum.
const FakeEnum = {
a: 0,
b: 1
} as const
Praca z obiektem FakeEnum
jest łatwa. Bo można łatwo, bez żadnych sztuczek uzyskać klucze i odpowiednio dobrać wartości obiektu.
IMHO, nie sądzę, że enum
jest najlepszą opcją do użycia w tym przypadku
PS Jeśli nie lubisz indeksu od zera w wyliczeniach, możesz ustawić swoją początkową wartość:
enum MyEnum {
ONE = 1, // 1
TWO // 2
}
num
to0
? Co jeślinum
to1.2
?Test[0]
wewnątrzgetType
, faktycznie zwróci pierwszy element w wyliczeniu,1.2
jednak zwróciundefined
. Korzystanie znumber
wymaga dodatkowej ochrony, aby zapewnić zwrócenie prawidłowego elementu wyliczenia.getType