-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Ensure enum members syntactically determinable to be strings do not get reverse mappings #57686
Ensure enum members syntactically determinable to be strings do not get reverse mappings #57686
Conversation
…et reverse mappings. Co-authored-by: frigus02 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, Andrew. I'm personally in favor of this approach.
Co-authored-by: Jan Kühle <[email protected]>
I personally agree with this, and so think I prefer this PR.
Is there some way we can instead use |
This PR moves in that direction, but we can't fully control emit by import { SomeOtherStringEnum } from './m';
enum Foo {
A = SomeOtherStringEnum.StringValue
} This works in non-isolatedModules |
@typescript-bot pack this |
Hey @andrewbranch, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build and an npm module you can use via |
FWIW esbuild does it the same way this PR does so I am all for it: https://jakebailey.dev/esbuild-playground/#v3=PTAEAEDMEsBsFMB2BDAtvAXKAxge0TAOYB0AVgM74BQA3laKAERIAuATgJ4AKu0iL5RlgDajYHwAm8AB7EB0xgF0ANPSaRcbVMhZCm8cqkZUAvlSogIMBCnRZJMueWlVoqAA6aWoGqABCAIIASqAmoJBsuKigAOQARshsMQDcVEgArtEAYri4PqABoAC8oAAGACQ0gUEmpaFUQA |
Jake and Ryan have expressed support for this. Can I have a ✅? 😄 |
Unblocks #56736?
In #56164, we decided that under
isolatedModules
, (from the notes) “enum members referencing another external enum must always be numeric, or explicitly converted to a string. Otherwise, it is an error.” This proposed rule has since undergone a number of interpretations on its way to an attempt to implement it. In #56153 (comment), Ryan stated that we should issue an error when “an enum initializer expression that isn't a string literal has a string type.” In #56736, @frigus02 worked off this statement, but interpreted “string literal” as any expression that could be evaluated to a known constant string value with single-file syntactic information only.An invariant guiding the decision is that error-free (under
--isolatedModules
) code should produce semantically equivalent JS betweents.transpileModule
andtsc
. Currently, that’s violated by this test case:This is currently error-free, but the emit varies.
tsc
:ts.transpileModule
:The problematic part isn’t the inlining of the value
"bar"
; it’s the fact that the transpiled output includes a reverse mapping when it absolutely shouldn’t.To fix this, we either need an error under
isolatedModules
or we need to fix thets.transpileModule
emit. Both Ryan’s formulation of the rule proposed in #56164 and @frigus02’s expanded interpretation in #56736 make this code an error. This PR fixes the emit by determining that the initializer is definitely going to be a string without looking at any type or extra-file info.I’m fine with adopting Ryan’s very strict rule instead of this, but it does seem like fairly low hanging fruit here. I’m less of a fan of the approach currently in #56736, since constant evaluation feels like the wrong thing to control whether a reverse mapping gets created, even though that’s what actually controls the emit today.