Reputation: 109503
In TypeScript, I'm defining an enum
, then I want a function to take a parameter whose value is one of the enum's values. However, TypeScript doesn't seem to do any validation on the value, and allows values outside of the enum. Is there a way to do this?
enum myenum {
hello = 1,
world = 2,
}
const myfunc = (num:myenum):void => console.log(`num=${num}`);
myfunc(1); // num=1 (expected)
myfunc(myenum.hello); // num=1 (expected)
//THE ISSUE: I'm expecting next line to be a TS compile error, but it is not
myfunc(7); // num=7
If I use a type
instead of enum
I can get something similar to what I'm looking for, but I lose some of the functionality of enum.
type mytype = 1|2;
const myfunc = (num:mytype):void => console.log(`num=${num}`);
myfunc(1);
myfunc(7); //TS Compile Error: Argument of type '7' is not assignable to a parameter of type 'mytype'
Upvotes: 8
Views: 2504
Reputation: 808
you might be expecting too much from enum in TS... :)
enum MyCoolEnum {
A = 1,
B = 2,
}
function test(data: MyCoolEnum) {
console.log(`Test = ${typeof data}`)
}
test(1)
test(MyCoolEnum.A)
test(500)
If you run this code above, you will see that all the lines print number
that means that behind the scenes it is translated to a number and that's why it accepts everything... Enums are usually just a good practice to avoid magic numbers and make the code more readable
On the other hand, if you stop using numeric enums and actually change the values for A and B to strings you will get:
TSError: ⨯ Unable to compile TypeScript:
dima.ts:10:6 - error TS2345: Argument of type '1' is not assignable to parameter of type 'MyCoolEnum'.
10 test(1)
~
dima.ts:12:6 - error TS2345: Argument of type '500' is not assignable to parameter of type 'MyCoolEnum'.
12 test(500)
~~~
at createTSError (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:423:12)
at reportTSError (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:427:19)
at getOutput (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:554:36)
at Object.compile (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:760:32)
at Module.m._compile (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:839:43)
at Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Object.require.extensions.(anonymous function) [as .ts] (/Users/odinn/.nvm/versions/node/v10.15.1/lib/node_modules/ts-node/src/index.ts:842:12)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
So what I'm trying to say is that if it's a numeric enum it's just cosmetics and it's treated as a number but if you make a string enum for example then it's actually tries to match the type
Upvotes: 1