Skip to content
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

After enum overhaul in TS 5.0, should we allow type assertion: number as Enum when number is not a valid enum? #54699

Closed
gpskalra opened this issue Jun 19, 2023 · 8 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@gpskalra
Copy link

gpskalra commented Jun 19, 2023

Bug Report

πŸ”Ž Search Terms

πŸ•— Version & Regression Information

This is a change in behavior since TS 5.0 as listed here https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#enum-overhaul

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

enum Color {
  Red = 1,
  Yellow = 2
}

let color1: Color = 3; // fail
let color2: Color = 3 as Color; // should this be allowed?

πŸ™ Actual behavior

This line does not throw an error

let color2: Color = 3 as Color; // should this be allowed?

πŸ™‚ Expected behavior

The aim of the enum overhaul was to catch errors where illegal values are assigned to the enum. With "as" being still present, it is still possible to assign illegal values.

@fatcerberus
Copy link

The entire purpose of type assertions is to allow assignments between related types that would otherwise be errors. myAnimal as Dog is legal because the types are related (Animal is the supertype), so I don't see any reason why 3 as Color (number is the supertype) wouldn't also be allowed.

@gpskalra
Copy link
Author

Forgive me if my understanding is incorrect, but I dont think thats entirely true. I think the purpose of type assertions would be help the compiler where it wont have sufficient information to make a decision. For example, getElementById can return any type of Dom element, we can help the compiler to consider it a HTMLCanvasElement if we are confident that is what is going to be returned. Similarly for the case of enums, if we are evaluating a number and we are confident that it will evaluate to a valid enum, it should be okay to use "as", while in this case, it is obvious to the compiler that 3 is not a valid Color, so why even allow the conversion using "as".

@MartinJohns
Copy link
Contributor

MartinJohns commented Jun 19, 2023

The enum could be used as a bitflag, in which case 3 would be a very valid value. Code like this exists, changing this behaviour would be a massive breaking change.

And fatcerberus is right, type assertions are an explicit way to override most type errors. That's why you can use a type assertion on object literal with missing or unmatching properties. If you're using a type assertion you always move outside of type safety.

@Andarist
Copy link
Contributor

This also reminds me about #53400 (an issue about enums and comparability) - so I'd say that this is very much intended.

@fatcerberus
Copy link

fatcerberus commented Jun 19, 2023

The enum could be used as a bitflag, in which case 3 would be a very valid value.

This is a good point. I'm pretty sure I remember hearing that the TS codebase itself does stuff like bitflagEnumVar = 0 as BitFlagEnum so this isn't just academic either. If people are actually doing this, then there's no other way around it, which means they'd have to rewrite it as as unknown as Enum--which you really don't want to risk normalizing since it's meant to be the nuclear option.

@Andarist
Copy link
Contributor

There is also this thing at play here - that is considered to be OK today:

const two = 2 as const as 3

Literal types are comparable within their domain regardless of actual values.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 19, 2023
@RyanCavanaugh
Copy link
Member

I can see the argument that the example in the OP feels more like a sidecast (Cat -> Dog) than a downcast (Animal -> Dog), but that distinction is really a heuristic one rather than something with a strong theoretical grounding. The restrictions on the as operator are there to prevent total boneheaded mistakes (string -> string[]), not to enforce the sort of implicit type safety you have when not using assertion operators.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

6 participants