Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript enums and external modules (browserify)

Until now I was using typescript internal modules and included 10s of script tags to bootstrap my app. I am currently in the process of converting the project to use external modules (using browserify) but I am stuck at how I should be converting enums.

I used to have something like:

mymodule.submodule {
     enum MyEnum {
        one,
        two,
        three
     }
}

and I would use it in other modules as:

var val:mymodule.submodule.MyEnum = mymodule.submodule.MyEnum.one;

and this compiled to js correctly. After converting the project to use external modules, I moved all my interfaces into *.d.ts files and thought of putting the enums in there as well, but of course this produced an error since there was no mapping between enum and number in js. I then moved the enums to *.ts files so that they will be compiled. Problem is that if I write them as:

export enum MyEnum{
    one,
    two,
    three
}

export enum OtherEnum {
    four,
    five,
    six
}

which works for requiring the enums in my code as:

import Enums = require('./enums');
var val = Enums.MyEnum.one; //this works
var val1: mymodule.submodule.MyEnum = Enums.MyEnum.one; //ERROR: incompatible types

BUT is incompatible with the mymodule.submodule.MyEnum type. So how can I have both a declaration for the enum type so I can declare variable types inside d.ts files, but also have the actual generated enum code depended upon (so that it will be loaded correctly) and used in .ts file?

Note: these enums are used across many modules, so including them in the same file they are used is not a solution.

UPDATE about interface declarations: it probably was not clear why I kept the original enum declarations in d.ts files so I am adding an example.

in interfaces.d.ts I currently have:

declare module mymodule.submodule {
    enum MyEnum{
       one,
       two,
       three
    }

    interface ISomething{
       aValue: MyEnum;
       aFunction: (anArg: MyEnum) => void;
    }
}

as far as I know I cannot using import statements in .d.ts files so how can I use one enum declaration in all cases?

like image 502
masimplo Avatar asked Nov 10 '22 10:11

masimplo


1 Answers

The enums need to be in a TS file because enums are compiled to JavaScript. When using modules, enums need to be imported to be used (even when just being used to define the type of a variable).

Change the code to the following:

import Enums = require('./enums');
var val1: Enums.MyEnum = Enums.MyEnum.one; // no error

Also, the enums should not be in mymodule.submodule if they are defined in enums.ts. Remove them from the definition file.

Regarding Update

To get the enums to work with the interfaces, you can move the interfaces out of the declaration file (interfaces.d.ts) and export them from a typescript file (ex. interfaces.ts):

import Enums = require('./enums');

export interface ISomething {
   aValue: Enums.MyEnum;
   aFunction: (anArg: Enums.MyEnum) => void;
}

Then you can use the interfaces like so:

import Interfaces = require('./interfaces');
import Enums = require('./enums');

var example: Interfaces.ISomething = {
    aValue: Enums.MyEnum.one,
    aFunction: (example: Enums.MyEnum) => { console.log('example'); }
};
like image 76
David Sherret Avatar answered Nov 15 '22 11:11

David Sherret