2

From enum:

enum Weekdays {
  Monday = 1,
  Tuesday = 2
}

We would like to get this type:

type WeekdaysType = 1 | 2
3
  • Weekdays itself is that union. Commented Oct 8, 2021 at 13:35
  • Not really. It looks like type widening happens and resulting type is a number: ``` enum Weekdays { Monday = 1, Tuesday = 2, }; const c: Weekdays = 5 // no error ``` Commented Oct 8, 2021 at 13:56
  • If you are inspecting the values of an enum you probably don't want an enum. Why not change it to const Weekdays = {Monday: 1, Tuesday: 2} as const; type WeekDays = (typeof Weekdays)[keyof typeof Weekdays] like this? What is the use case here? Commented Oct 8, 2021 at 14:04

4 Answers 4

1

If, instead of the numeric enum, you create a const object whose prototypes correspond to the numeric values your original enum had:

const Weekdays = {
  Monday: 1,
  Tuesday: 2,
} as const;

Then, you can define a type with the same name as the object above:

type Weekdays = (typeof Weekdays)[keyof typeof Weekdays];

This type is the union of the types of the object properties, i.e., 1 | 2. That's why you need the as const assertion above so that TypeScript infers the literal types 1 and 2 for Monday and Tuesday, respectively. Otherwise, it would infer the broader type number and the type Weekdays would result in number as a consequence.

Both typeofs aren't JavaScript's typeof despite taking a value (i.e., the const object) as their operand. They correspond to TypeScript's typeof because they are being used in the type space (they are inside a type definition):

type Weekdays = (typeof Weekdays)[keyof typeof Weekdays];
                 ^^^^^^                 ^^^^^^

Finally, note that in this solution, you have both a type and a value with the name Weekdays: the type Weekdays and the const object Weekdays. There are no clashing issues here since they live in different spaces: the type and value spaces.

Sign up to request clarification or add additional context in comments.

1 Comment

Accepting as this is closest to what is wanted.
0

With TypeScript 4.1+, you can use template literal types:

enum Weekdays {
  Monday = 1,
  Tuesday = 2,
};

type WeekdaysType = `${Weekdays}`;

Caveat: This only works with enums that have string values, so for your particular use case, WeekdaysType would be "1" | "2", rather than 1 | 2. As far as I'm aware, there's no current way to dynamically extract numeric enum values into a union type.

TypeScript Playground

4 Comments

Does not work as created type is: type WeekdaysType = "1" | "2"
Please see my edit with the caveat. As far as I'm aware, as of TS 4.4, there's no way to get a union type from numeric enum values.
Also, I don't believe there's any way to convert a string literal type to a numeric literal type dynamically.
All this does is convert to string; the original type already is the union of numbers.
0
enum Code {
    a = 111,
    b = 222,
    c = 'abc'
}

type StrToNum<Str> =
  Str extends `${infer Num extends number}`
    ? Num
    : Str

type res = StrToNum<`${Code}`>;

2 Comments

Type of res is: type res = number | "abc" what I would like to have is type res = 111 | 222 | "abc".
asker is only asking about numeric values. why do you have a string :p
-1

Instead enum, you can use union types

const Weekdays {
  Monday: 1,
  Tuesday: 2,
} as const;

type Union<T> = T[keyof T];

type WeekdaysType = Union<typeof Weekdays>; // type WeekdaysType = 1 | 2

// you can use like enum
console.log(Weekdays.Monday) // 1

Numeric enums are not type safe

enum ZeroOrOne {
  Zero = 0,
  One = 1
}
const zeroOrOne: ZeroOrOne = 2; // no error!!

1 Comment

it should produce an error 0_o At least it produces for me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.