8

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?

Example

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

Alternative

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'
2
  • Have you seen this question and its answers? stackoverflow.com/questions/43804805/… Commented Apr 23, 2020 at 1:22
  • @JonahBishop Apparently I had, since I had upvoted the question and an answer. :) That doesn't quite help me. I can add a condition in my function like if(!Object.values(myenum).includes(num)) throw('Illegal Argument'); but that makes it a runtime error when I'd rather it be something typescript can identify at compilation. Commented Apr 23, 2020 at 17:14

1 Answer 1

1

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

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

3 Comments

thanks, this all kind of confirms what i've already seen. i'm working with some code where the enum was defined 2 years ago and is used in a lot of places, so i can't easily change to a type. but in my new function, i'd like to be able to have typescript verify that i'm passing in a value that is actually in the enum. is there a way to do that, or am i just out of luck?
not that I know of, only thing I can think of is adding some validation logic... or maybe if you change the enum and add a string value to it which will stop making it a numeric enum, maybe that can help... sort of a hack though
seems this is "by design" for now- github.com/microsoft/TypeScript/issues/36756

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.