Closed
Description
Bug Report
Compiler shouldn't allow number
to be used where enum
is expected.
🔎 Search Terms
number where enum expected
🕗 Version & Regression Information
- 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 enums_and_function_params
- I was unable to test this on prior versions because _______
⏯ Playground Link
Playground link with relevant code
💻 Code
export enum StatusEnum {
Cancelled = 4,
Paid = 6
}
export interface Summary {
readonly status: number;
}
export class TripSummary {
private readonly status: StatusEnum;
public constructor(dto: Summary, status: number) {
this.status = status; // status is number, but allowed to be assigned to an enum field
this.setFullStatus(dto.status); // dto.status is number, but allowed to be passed as an enum param
}
private setFullStatus(status: StatusEnum): void {
console.log(status);
}
}
🙁 Actual behavior
Compiler allows number
to be used where enum
is expected. It's incorrect because narrowing conversion is done implicitly while the compiler cannot make sure that a value passed as the enum param is within a range of the enum values.
🙂 Expected behavior
Implicit conversions from number
to enum
should generate an error requiring an explicit conversion to be performed (for exampe, using as
)
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
fatcerberus commentedon Mar 16, 2022
This is intentional because numeric enums are often used as bitfields, e.g.
FooEnum.Foo | FooEnum.Bar
is typed asnumber
because it’s not explicitly part of the enum. You can use string-valued enums for stricter checks.AbakumovAlexandr commentedon Mar 16, 2022
Can you provide a full line of code to demostrate what you've meant? I'm not sure how this is related to allowing implicitly assigning numbers into enum typed members.
AbakumovAlexandr commentedon Mar 16, 2022
@RyanCavanaugh What is the justification for 'Working as Intended'? Especially in 'strict' mode?
fatcerberus commentedon Mar 16, 2022
computedFlags
should ideally be assignable back to the enum type, ifobj
is using it as a bitfield. However it’s currently typed asnumber
because its actual value is not (necessarily) part ofFlagsEnum
. Thus why this type hole is present.AbakumovAlexandr commentedon Mar 16, 2022
If you needed this type 'abuse' (in my opinion, sorry if too harsh :) ), you always could shut up the compiler explicitly:
So, fixing this TS compiler bug doesn't affect your use case and can't be the justification for the missing type safety related to enums in 'strict' mode.
RyanCavanaugh commentedon Mar 16, 2022
@AbakumovAlexandr because we did this behavior on purpose
fatcerberus commentedon Mar 16, 2022
I’m not making any value judgments here, just telling you why the behavior is the way it is, and why it’s intentional. It’s also unlikely to change—at least, not without an additional opt-in compiler flag—as it would be pretty disruptive to a lot of code in the wild.
AbakumovAlexandr commentedon Mar 16, 2022
Can you elaborate: what is the purpose?
fatcerberus commentedon Mar 16, 2022
🤦♂️
RyanCavanaugh commentedon Mar 16, 2022
So that you can use bitflag-style enums without getting an error, as described above.
AbakumovAlexandr commentedon Mar 16, 2022
So, what should I do to ensure that the value in an enum-typed member is actually the one I've defined in my enum without any runtime code?
RyanCavanaugh commentedon Mar 16, 2022
There currently isn't a way to do that. The suggestion tracking adding a way to do so is #32690
fatcerberus commentedon Mar 16, 2022
Use a string-valued enum.
RyanCavanaugh commentedon Mar 16, 2022
You could also use a
const
-style enumfrom there the code sample works as desired
8 remaining items