Skip to content

Suggestion: Accessing const enum member using variables with preserveConstEnums=true #13753

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
Knagis opened this issue Jan 30, 2017 · 6 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@Knagis
Copy link
Contributor

Knagis commented Jan 30, 2017

Currently it is not possible to access const enum member at runtime by using string or number indexer. This makes sense because by default the declarations for these enums are not emitted in the JS code.

However, we can use preserveConstEnums:true compiler option to both emit the enum declaration in the JS and to have the enum usages still be converted to simple numbers.

As such, it would make sense that with preserveConstEnums:true the enum members should be accessible at runtime as well.

const enum Foo {
    foo1 = 1,
    foo2 = 2 
}

// both lines fail with:
// A const enum member can only be accessed using a string literal.
let fk: "foo1" | "foo2" = Foo[1];
let f = Foo[fk];
@mhegazy
Copy link
Contributor

mhegazy commented Jan 30, 2017

--preserveConstEnums is intended only to keep the enum around for debugging scenarios. If you want the enum to stick around and be treated as such by the type system, use regular enums.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jan 30, 2017
@Knagis
Copy link
Contributor Author

Knagis commented Jan 30, 2017

My intention is that our library code internally would use the enum (that is compiled to numeric constants). However the consumers of the library would be expected to either use the enum or string constants (that the library would convert to enum itself).

This works very nicely with const enum and preserveConstEnums:true. It does require cast to <any> but the transpiled code works properly.

namespace Bar {
  export const enum Foo {
      foo1 = 1,
      foo2 = 2 
  }

  let fk: "foo1" | "foo2" = (<any>Bar).Foo[1];
  let f = (<any>Bar).Foo[fk];
}

transpiles to

var Bar;
(function (Bar) {
    var Foo;
    (function (Foo) {
        Foo[Foo["foo1"] = 1] = "foo1";
        Foo[Foo["foo2"] = 2] = "foo2";
    })(Foo = Bar.Foo || (Bar.Foo = {}));
    var fk = Bar.Foo[1];
    var f = Bar.Foo[fk];
})(Bar || (Bar = {}));

@mhegazy
Copy link
Contributor

mhegazy commented Jan 30, 2017

That is not a supported use case of enums. they are either in all the way (enums) or inlined all the way (const enums). I suspect you are looking for an optimization for enum values along the lines of #6805

@Knagis
Copy link
Contributor Author

Knagis commented Jan 31, 2017

Yes, the goal is to inline the enum values.

However, is there some detail I am not seeing that prevents using the const enum and preserveConstEnums:true for this purpose in general use case? For me it seems that while it was not intended for that, it does exactly what is needed (except requiring the <any> cast).

@mhegazy
Copy link
Contributor

mhegazy commented Jan 31, 2017

That is not the indented design. the compiler makes assumptions about the emitted code based on this flag, and it is not possible to enforce this across different components. I believe what you are looking for is a regular enum, with an emit optimization to inline constants. again this is not supported at the moment.

@Knagis
Copy link
Contributor Author

Knagis commented Jan 31, 2017

Thank you for the information!

I suppose that we will use plain enums and once we get closer to release, we will probably try to modify the compiler to emit inline constants for all enums.

@Knagis Knagis closed this as completed Jan 31, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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

2 participants