Mac OSX Sierra
Versions.
1.0.0-beta.17
Repro steps.
ng new --prefix=t check-enum
cd check-enum/
ng serve
then add to main.ts (no matter, may be any *.ts)
declare namespace Sts {
export const enum A{
a, b, c
}
}
console.log(Sts.A.a, Sts.A.b);
main.bundle.js:65131 Uncaught ReferenceError: Sts is not definedActual in
main.bundle.js
console.log(Sts.A.a, Sts.A.b); (see at Source panel of Chrome Developer Tools)
main.bundle.jsconsole.log(0 /* a */, 1 /* b */);
If I run tsc from src directory, this code will be in dist/out-tsc, as expected. TypeScript is OK!
I donn't know, where is a mistake, in angular-cli or its configuration or deps. Generated code is same, as without
constkeyword. This is very strange.
This is blocking me as well. version 1.0.0-beta.25.5
We also ran into this while upgrading to a Webpack-based/AOT-enabled build system. We have some tooling set up that automatically generates d.ts files for all of our web-facing model classes. This maps native enums - very correctly - to const enums.
The automatically generated .d.ts file:
declare module server {
const enum Status {
OK
}
}
The problem arose when we tried to use these enum values directly:
export function processStatus(status: server.Status) {
switch (status) {
server.Status.OK:
// Custom code here
break;
}
}
Luckily code like this was few and far-between so I solved the issue by replacing the generated enums with their constant values. This solution is of course very far from ideal: we lose type safety and the code becomes harder to read. Non-ambient const enums are properly transpiled.
Since this issue is 6 months old and is a pretty severe codegen bug some official word would be really appreciated.
It still be very annoying bug.
Did anybody try to fix or "investigate" this?
I found explanation: Const enums are preserved when using transpileModule
In short: transpileModule compiles in single-file mode, so it don't know about enums in other files.
Now I don't use const enums(
preserveConstEnums = true not works in ambient declaration files (*.d.ts)
Third way is too complex and takes much time. It is very expensive in support.
Thanks!
Dear CLI team! Please give some feedback on the issue.
I have similar setting as Gustorn (post from 10 Apr.) and feel very uncomfortable modifing generated code just to satisfy the CLI tooling pipeline.
"awesome-typescript-loader" still does not have any solution for the problem, so may be you can replace the loader?
Thanks!
@taras-demyanets @KhodeN You can compare enums using valueOf function of enums.
namespace Validation {
export const enum A {
a, b, c
}
}
const x: Validation.A = Validation.A.c;
console.log(x.valueOf() === Validation.A.b); // return false
switch (x.valueOf()) {
case Validation.A.a:
console.log('a');
break;
case Validation.A.b:
console.log('b');
break;
case Validation.A.c:
console.log('c');
break;
default:
console.log('none');
break;
}
@sumitarora The problem isn't that we can't compare const enums, it's that the values we're comparing against aren't transpiled (and thus result in runtime errors). If we take your example (a little shortened):
// Ambient declaration in another .d.ts file
namespace Validation {
export const enum A {
a, b, c
}
}
// Usage code
const x: Validation.A = Validation.A.c;
switch (x.valueOf()) {
case Validation.A.a:
console.log('a');
break;
}
Should transpile to:
var x = 2;
switch (x.valueOf()) {
case 0:
console.log('a');
break;
}
But instead transpiles to:
var x = Validation.A.c;
switch (x.valueOf()) {
case Validation.A.a:
console.log('a');
break;
}
And naturally it cannot find Validation.A.c and Validation.A.a at runtime.
I've many enums in my project and that I can't use them is a really show stopper for me to use the cli.
Currently I am using pure webpack 2 and there everything is workingfine with the Enums here my TS loader is the following rule
test: /\.ts$/,
use: [
'@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
'awesome-typescript-loader',
'angular2-template-loader'
],
I have a .NET MVC Project and I am using TypeLite to generate TypeScript Enums out of my C# Enums. Here a Enums.ts file is created with many Enums inside like
module Internal.Notification.DomainModel {
export const enum NotificationType {
Information = 0,
Success = 1,
Warning = 2,
Error = 3
}
}
module Internal.Repository.DomainModel {
export const enum SortDirectionEnum {
Ascending = 0,
Descending = 1
}
}
I am currently trying to migrate from my own webpack 2 build to the cli but currently it seems not possible.
@imiuka your Solution with "preserveConstEnums" is not working here and the third solution is too complex, there I can stay with my current own WebPack Build Setup.
@Gustorn why is the third Solution from @imiuka not implemented in the CLI with an addional Parameter or so and perhaps can someone explain me why my TypeScript Loader setup makes no Problems with the Enums?
A working solution for such a common problem would be really nice.
This is still a blocking issue for me.
Repro steps:
module enums {
export const enum myEnum {
value0 = 0
}
}let x = enums.myEnum.value0;Expected:
The app builds and runs without error
Actual:
The app builds without error. However, the module containing your enum will not be defined at runtime. Error message: Uncaught ReferenceError: enums is not defined.
The module not being defined at runtime is actually expected. The compiler _should have_ replaced the enum reference with the value because this enum is defined as a constant. This is unexpected and undesirable behavior.
This issue prevents me from using angular-cli in projects where I have split out enumerations into their own files for reuse. What is worse is that I can not use tools like typelite to automatically translate my enumerations from .Net to typescript.
@angular/cli: 1.0.4
node: 6.10.2
os: win32 x64
@angular/common: 4.1.3
@angular/compiler: 4.1.3
@angular/core: 4.1.3
@angular/forms: 4.1.3
@angular/http: 4.1.3
@angular/platform-browser: 4.1.3
@angular/platform-browser-dynamic: 4.1.3
@angular/router: 4.1.3
@angular/cli: 1.0.4
@angular/compiler-cli: 4.1.3
The worst thing is that this is a solved problem in ts-loader. I understand the desire for higher performance (transpileModule _is_ faster) but at least add an option for us to use the slower but correct version.
As a temporary workaround you can actually import const enums explicitly and it will work as expected. The problem is that most tools generate definition - and not regular - TS files.
Indeed.
As for the workaround, I agree that explicit importing should work for cases where I we modify the source file. AFAIK we would have to modify that enums file to start with exportmodule enums .... Is there a way to explicitly import a file which does not export?
This is the crux of the issue with Typelite. The enum file generated by Typelite has a structure just like in my steps. I believe I can not explicitly import a Typelite enum since it is generated and, as far as I can tell, there is no way to alter how the module is declared when it is being generated.
We want to use CLI in out current project for better updateability, but could not switch due to the enum problem.
We also use Typlite to generate our enums.
Is there anybody investigating this problem and can say when the problem will be solved?
@lordzero83 I found the reason: https://github.com/angular/angular-cli/issues/2741#issuecomment-294696150
It's need for performance. Each ts file compiles separately, without information from other files. While transpileModule is used, the trouble stays.
The thing is, ts-loader with its fork-checker-plugin beats awesome-typescript-loader in some of our projects and it actually generates correct code.
@KhodeN it would be great if the cli could provide a configuration parameter, where it ignores the performance improvements so that you can use the cli also with const enums (TypeLite) and a slower performance would be ok for me.
This is a major issue for us, as well. The fact that it's a runtime error makes it even worse because it's really easy to miss. @hinaria , what webpack plugin are you using to do the replacement?
This seems to still be an issue but in a different way, and it's causing issues in other module repos: https://github.com/swimlane/ngx-datatable/issues/927
With CLI 1.5+ and Angular 5, the use of transpileModule has been eliminated. Note that Angular 4 uses the previous compiler pipeline so if const enum support is required please update to Angular 5+.
Tested this out and it works! Thanks for fixing it 馃憤
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
@sumitarora The problem isn't that we can't compare const enums, it's that the values we're comparing against aren't transpiled (and thus result in runtime errors). If we take your example (a little shortened):
Should transpile to:
But instead transpiles to:
And naturally it cannot find
Validation.A.candValidation.A.aat runtime.