Reputation: 4516
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
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
Upvotes: 7