Hivaga
Hivaga

Reputation: 4516

Typescript extending Enum

The case is you have a list of constants or Enum how you can do it ?

Here is the pseudo example code:

enum MyList
{
    A,
    B
}

enum MyList2
{
    C
}


function test<T>(input:MyList | T):void
{

}

test<MyList2>(123) // compiler does not identify that 123 is not a supported

Upvotes: 3

Views: 6490

Answers (1)

jcalz
jcalz

Reputation: 329258

This is a longstanding issue with numeric enums. For whatever reason (some backwards compatibility they can't break), a number is seen as assignable to a numeric enum, so you can do this with no error:

enum E {
  V = 100
}
const num = 100;
const e: E = num; // no error 🤔

What's more, numeric enums are also intended to act as bit fields, and therefore they intentionally don't require that a value of an numeric enum type is one of the specific declared values:

enum Color {
  RED = 1,
  GREEN = 2,
  BLUE = 4
}
const red: Color = Color.RED; // 1
const yellow: Color = Color.RED | Color.GREEN; // 3 🤔
const white: Color = Color.RED | Color.GREEN | Color.BLUE; // 7 🤔
const octarine: Color = Math.pow(Color.BLUE - Color.RED, Color.GREEN); // 9 🤪

Yeah, I don't know why you can do any math you'd like with a numeric enum, but you can. The upshot is, essentially any number is assignable to any numeric enum, and vice versa.


If you want to prevent this you might want to give up on actual enums and instead make your own types and values with behavior you control. It's more verbose but it might meet your needs:

const MyList = {
  A: 0,
  B: 1
} as const;
type MyList = typeof MyList[keyof typeof MyList]

const MyList2 = {
  C: 0
} as const;
type MyList2 = typeof MyList2[keyof typeof MyList2]

Those behave similarly to your old enums (although there are some missing types) but they will be much more strict about behavior:

function test<T>(input: MyList | T): void {}

test(0); // okay
test(1); // okay
test(2); // okay, 2 is inferred as T
test<MyList2>(123); // error! 123 is not assignable to 0 | 1

Link to code

Upvotes: 7

Related Questions