Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: Infer enum value type from enum type

I wrote a function returning all values of a given enum as array. The implementation works, but I have a problem with the type of the return value.

enum Foo {
    FOO_1 = "FOO_1",
    FOO_2 = "FOO_2",
}

function getEnumValues<T>(e:T): T[] {
    let keys: string[] = Object.keys(e);
    keys = keys.filter(key => e[key] !== undefined);
    return keys.map(key => e[key]);
}

const fooValues:Foo[] = getEnumValues(Foo);

I get this error:

Error:(46, 7) TS2322: Type '(typeof Foo)[]' is not assignable to type 'Foo[]'. Type 'typeof Foo' is not assignable to type 'Foo'.

How can I change the signature of getEnumValues() in order to return the type Foo[] here?

like image 857
Reducer Avatar asked May 08 '18 06:05

Reducer


People also ask

Can I use enum as a type in TypeScript?

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

Is enum a type or value TypeScript?

Enums or enumerations are a new data type supported in TypeScript. Most object-oriented languages like Java and C# use enums. This is now available in TypeScript too. In simple words, enums allow us to declare a set of named constants i.e. a collection of related values that can be numeric or string values.

How does TypeScript compare enum values?

To compare enums, use dot notation to get the value for a specific enum property and compare it to another value, e.g. if (MyEnum. Small < 2) {} . The values for numeric enums, without provided initial value, are auto-incrementing integers, starting at 0 .


1 Answers

You need to change the definition a bit to infer the type of the enum member, right now T will be the enum object itself (aka typeof T)

enum Foo {
    FOO_1 = "FOO_1",
    FOO_2 = "FOO_2",
}

function getEnumValues<TEnum, TKeys extends string>(e: { [key in TKeys]: TEnum }): TEnum[] {
    let keys = Object.keys(e) as Array<TKeys>;
    keys = keys.filter(key => e[key] !== undefined);
    return keys.map(key => e[key]);
}

const fooValues: Foo[] = getEnumValues(Foo);

Note that while this works for enums, it will work for any object it is not restricted to enums

like image 93
Titian Cernicova-Dragomir Avatar answered Sep 28 '22 20:09

Titian Cernicova-Dragomir