Skip to content

Autogenerated Enum or with numbers value are not generating a TS2345 as expected (gives valid use when is not) #51987

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
danyg opened this issue Dec 21, 2022 · 6 comments
Labels
Duplicate An existing issue was already created

Comments

@danyg
Copy link

danyg commented Dec 21, 2022

Bug Report

When a function receives as argument an Enum with values autogenerated or defined numeric values, It fail to check invalid given arguments allowing to compile broken code.

It works as expected when using Enums with string values, or when Forcing to check against a type that has the numbers as piped values. (type ValidEnumVal = 1 | 2 | 3;) UNLESS those values are populated from the enum (type ValidEnumVal = MyEnum.On | MyEnum.Off)

🔎 Search Terms

is:open label:Bug enum
is:open label:Bug enum number
is:issue is:open label:bug enum 2345

🕗 Version & Regression Information

Can be reproduced with 4.9.4

  • This is a crash
  • This changed between versions ______ and _______
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
  • I was unable to test this on prior versions because _______

⏯ Playground Link

Playground link with relevant code

💻 Code

🙁 Actual behavior

enum SwitchState {
  ON,
  OFF,
}

const isSwitchOn = (state: SwitchState) => state === SwitchState.OFF;

isSwitchOn(5); // no validation error even 5 is not a valid value nor complies with SwitchState
enum SwitchState {
  ON = 1,
  OFF = 2,
}

const isSwitchOn = (state: SwitchState) => state === SwitchState.OFF;

isSwitchOn(5); // no validation error even 5 is not a valid value nor complies with SwitchState

with string works fine

enum SwitchState {
  ON = 'on',
  OFF = 'off',
}

const isSwitchOn = (state: SwitchState) => state === SwitchState.OFF;

console.log(isSwitchOn(5)); // Argument of type '5' is not assignable to parameter of type 'SwitchState'.ts(2345)
console.log(isSwitchOn('3'));// Argument of type '"3"' is not assignable to parameter of type 'SwitchState'.ts(2345)

Using | in the type also works (I think internally number Enums should be treated like this case)

type SwitchState = 1 | 2;
const isSwitchOn = (state: SwitchState) => state === 2;
console.log(isSwitchOn(5)); // Argument of type '5' is not assignable to parameter of type 'SwitchState'.ts(2345)

FAILS if the numbers are coming form a enm
Using | in the type also works (I think internally number Enums should be treated like this case)

enum SwitchState {
  ON = 1,
  OFF = 2,
}
type SwitchStateHelpr = SwitchState.ON | SwitchState.OFF;
const isSwitchOn = (state: SwitchStateHelpr) => state === SwitchState.OFF;
console.log(isSwitchOn(5)); // Valid (BUG)

🙂 Expected behavior

enum SwitchState {
  ON,
  OFF,
}

const isSwitchOn = (state: SwitchState) => state === SwitchState.OFF;

isSwitchOn(5); // Argument of type '5' is not assignable to parameter of type 'SwitchState'.ts(2345)
@MartinJohns
Copy link
Contributor

Duplicate of #26362, which provides plenty of reasoning for this behaviour. Used search terms: enum number in:title

@danyg
Copy link
Author

danyg commented Dec 21, 2022

@MartinJohns I only searched for open issues, as looks like a bug, talks like a bug and moves like a bug, and can be reproduced from TS 3.3.3 onwards therefore it looks as a non-deal with open issue to me.

I see that makes sense in that context, Please can you see why it looks a bug to me and my team, and why this inconsistency might cause people to use convoluted and anti-pattern solutions to avoid enums like this video https://www.youtube.com/watch?v=jjMbPt_H3RQ.

Why it make sense to have enums working perfectly in generics, and broken in the most basic use case? Why to make compilation faster? is faster better than accurate in a tool that is main propose is to be accurate? 🤔

@fatcerberus
Copy link

There are no open issues precisely because it’s not a bug. Numeric enums are often used as bitfields, where you need to be able to combine them like E.A | E.B, therefore any number is assignable to them. This is working as intended.

The TS type system is not designed to be mathematically sound or “accurate” as you put it. It is designed to, quoth the design goals, “strike a balance between correctness and productivity”. It is very pragmatically designed and there are a lot of these kinds of inconsistencies as a result.

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Dec 21, 2022
@andrewbranch
Copy link
Member

What @MartinJohns and @fatcerberus said is true, but also, the behavior is changed to what you’re looking for in 5.0 via #51561. If you update the playground version to "Nightly," every call in your example is an error, as you expect.

@fatcerberus
Copy link

Sadly, this is still not an error in the nightly:

let x = 5;
console.log(isSwitchOnNum(x));  // no error

It would be amazing if it could eventually be made so that E.A | E.B was allowed (i.e. inferred as the enum type) but arbitrary numbers were not.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants