TypeScript: Compiling TS with enum strings for 2-way mapping (the old way) causes invalid declaration file (but compiles ok).

I noticed something seems inconsistent. I have a mapping that was working for mapping file types and extensions, which was VERY convenient, and allowed tracking them as proper types (other than string). The .d.ts file is generated ok, without errors! However, if I take that declaration file and add it to another project it breaks.

TypeScript Version: 2.5 (that is the only version I have that was updated with VS 2017)

Code

enum FileTypesMap {
    FileTypeAExt = <any>".aext",
    FileTypeBExt = <any>".bext"
}
enum FileTypesMap {
    FileTypeCExt = <any>".cext",
    FileTypeDExt = <any>".dext"
}

Expected behavior:

file.d.ts output:

declare enum FileTypesMap {
    FileTypeAExt = <any>".aext",
    FileTypeBExt = <any>".bext"
}
declare enum FileTypesMap {
    FileTypeCExt = <any>".cext",
    FileTypeDExt = <any>".dext"
}

(or similar, doesn’t matter)

Actual behavior:

file.d.ts output:

declare enum FileTypesMap {
    FileTypeAExt,
    FileTypeBExt,
}
declare enum FileTypesMap {
    FileTypeCExt,
    FileTypeDExt,
}

ERROR: In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element.

Yes, I am well aware of the issues of enum { A = <any>'B', 'B' = <any>'A' }, and that’s besides the point. If it compiles correctly, the d.ts file should also be proper - it should not be complaining about implementation stuff. 😉

I’m also aware of string enums, and that is also not the point of this code. The point is a mapping between a file type name and an extension (both ways). There are other ways I’m sure, which is also not the point since this should work. Keep in mind this is part of a framework that also allows others to extend the file type names and extensions. I imagine there are other ways, but if this way compiles, again, the declaration should not be complaining.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

And this is pretty!?

enum FileTypesMap {
    FileTypeAExt = <any>".aext",
    FileTypeBExt = <any>".bext"
}

🤷‍♂️

when you try to do stuff you know should work perfectly fine in JS

Enums are a TypeScript only construct… so no, it never worked perfectly fine in JS.

Yes, that will fail, of course, but I’m not using it that way, and as I said, it does not fail the way I put it (only the way you put it). 😉 What I mean is that I used it that way since last year+ (for strong typing before string enums) and it worked just fine - because I knew it wasn’t a number!!! 😉 Anyhow, I didn’t realize <any> was still treated as a number type (which makes sense) so I do get it. It would be nice if we allowed some sort of string mapping this way, but I guess I’ll have to use another workaround, as typical again. TS is great, except when you try to do stuff you know should work perfectly fine in JS, but it fights with you (like this). I guess I’ll just use string enums and create a function to make this mapping instead; certainly less ‘framework’ friendly.

It compiles just fine

no. consider FileTypesMap.FileTypeAExt.toFixed(), this will fail at runtime with string.toFixed is not a funciton.

so it should be supported.

no. it was not supported. we never claimed it was.

If you don’t want to support it, then make it fail at compile time

we do. you casted your way to any. same as (<any>"string").toFixed(); that one is not supported either.

I should add that the “expected” behavior you list never worked.

Do not use numeric enums to add strings. that is not a supported behavior.

Starting from TS 2.4, you can use string enums