Sebastian Sebastian - 1 year ago 78
TypeScript Question

Named Constructors and Nested Types in TypeScript Library Definition File - "Duplicate Identifier" Error

I am trying to create a TypeScript library definition file for an existing Javascript library. What's specifically challenging is that we have "named constructors" in our library and nested types.

In Javascript you can do this, e.g.:

var some = new MyModule.SomeClass(); //some is of type 'MyModule.SomeClass'
var some2 = new MyModule.SomeClass.WithValue("value"); //some2 is of the same type as some

The problem comes when there is also an inner enumeration defined in the class like this:

var enumValue = MyModule.SomeClass.SomeEnum.VALUE_A;

I have it working with nested classes and interfaces, however for some reason the typescript compiler chokes when I try to declare a nested enumeration. This is what I have for the above scenario in some

declare module MyModule {
export interface SomeClass_Interface {
foo: number;

export module SomeClass {
export interface InnerClass { bar: string; }
//enum SomeEnum { VALUE_A, B, C }

export var SomeClass: {
new (): MyModule.SomeClass_Interface;
WithValue: {
new (bar: string): MyModule.SomeClass_Interface;

The above works great1 and compiles, but as soon as I comment in the
the compiler gives
Duplicate identifier 'SomeClass'
at the line of the variable declaration. Is this a compiler bug (I am using because the compiler thinks it has to create a declaration because of the enumeration constants or am I doing something wrong?

How can I write a definition file in order to support nested types/named constructors and nested enumerations?

Note that this question is specifically about library definitions. I am not trying to create new classes like this with typescript, I would like to use an existing library instead that cannot be modified.

1well, I had to rename the interface to use the suffix, but this at least works and does not influence the behavior). I was not able to get it to work with the interface using the same name as the module and the variable declaration, although from my understanding from this discussion, this should actually work. It didn't in all my tests, though.

Answer Source

You could model it like this:

declare module MyModule {
    export class SomeClass {
        static WithValue: {
            new (bar: string): SomeClass;

    export module SomeClass {
        export interface InnerClass { bar: string; }
        export enum SomeEnum { VALUE_A, B, C }

Unfortunately there isn't any other way to model an object with both enum members and construct signatures.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download