TypeScript: How do I import a type definition module? (error TS2656: …not a module)

Hello! I’m sorry to both you with something that is surely my problem, but I would love to get this figured out. I have been coding for 17 years and this has got me really stuck!!! I must be missing something stupid.

FWIW, I have read documentation over and over, I have posted to StackOverflow, and I have not found a solution yet. I have to be humble and ask for support to try to overcome this.

TypeScript Version:

1.8.10

Code

I have a simple npm module, emitter20, that I am trying to add type definitions to. Here is all 20 lines of its source:

module.exports = function() {
  var subscribers = []
  return {
    on: function (eventName, cb) {
      subscribers.push({
        eventName: eventName,
        cb: cb
      })
    },
    trigger: function (eventName, data) {
      subscribers
        .filter(function (subscriber) {
          return subscriber.eventName === eventName
        })
        .forEach(function (subscriber) {
          subscriber.cb(data)
        })
    }
  }
}

Here is the index.d.ts file in the emitter20 project root:

declare module 'emitter20' {
  interface IEmitter {
    on: (eventName: string, cb: (data?: any) => void) => void;
    trigger: (eventName: string, data?: any) => void;
  }
  interface EmitterFactory {
    new(): IEmitter;
  }
  export = IEmitter;
}

I have also tried this:

declare module 'emitter20' {
  export interface IEmitter {
    on: (eventName: string, cb: (data?: any) => void) => void;
    trigger: (eventName: string, data?: any) => void;
  }
  export interface EmitterFactory {
    new(): IEmitter;
  }
}

And from others’ suggestions, I have also tried this:

declare module 'emitter20' {

    function Emitter(): Emitter.IEmitter;
    namespace Emitter {
        interface IEmitter {
            on: (eventName: string, cb: (data?: any) => void) => void;
            trigger: (eventName: string, data?: any) => void;
        }
    }


    export = Emitter;
}

I try to import it into my project like this:

import IEmitter = require('emitter20')

export interface SwapManager extends IEmitter {
  manager: any;
}

Or this:

import * as emitter from 'emitter20'

but I get the following error:

error TS2656: Exported external package typings file './node_modules/emitter20/index.d.ts' is not a module. Please contact the package author to update the package definition.

With other attempts, I have gotten a “cannot find module” error as well. I have tried many things at this point to no avail.

How do I define and import the type definition for the emitter20 module?

Thank you so much.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 45 (26 by maintainers)

Most upvoted comments

There is a lot of confusion around this topic because there are many different ways to write these definitions depending on your target audience.

declare namespace Emitter {
    export interface Emitter {
        on: (eventName: string, cb: (data?: any) => void) => void;
        trigger: (eventName: string, data?: any) => void;
    }
}

declare module 'emitter' {
    import E = Emitter.Emitter;
    export = E;
}

could anybody explain this on my simple example:

//commonjs-export-function.js
module.exports = function() {
    return 'func';
};
//commonjs-export-function.d.ts
declare function func(): string;
export = func;
//main.ts
import func from './commonjs-function';

console.log(func());

When I run tsc I get this error:

tsc main.ts && node main.js
main.ts(1,8): error TS1192: Module '"/Users/aleksandar/projects/typescript-playground/commonjs-function"' has no default export.

As @aluanhaddad noted, we need to know how this module is consumed. I am assuming here it is a node-only module.

I would recommend using export= on an identifier. so your module would look like:

// emitter20/index.d.ts

declare class Emitter {
    on: (eventName: string, cb: (data?: any) => void) => void;
    trigger: (eventName: string, data?: any) => void;
}

export = Emitter; // this exports a function that returns objects of type Emitter, and a type called Emitter

you would import this as:

import emitter20 = require("emitter20");
var emitter = new emitter20();
emitter.trigger("event"); 

In typescript declarations can “merge”. an example of this is multiple declarations of the same interface, each adding a set of properties. another is merging a namespace with only types and a value. when using export = <identifier> you are exporting all meanings of this name (i.e. both the namespace Emitter and the value Emitter).

you can read more about this in http://www.typescriptlang.org/docs/handbook/declaration-merging.html

From the example above, emitter20 is an existing npm package. my sample assumes that you will be importing this from node_modules\emitter20. The index.d.ts should live next to index.js in the package.

declare module "emitter20" adds a new name (“emitter20”) to the global namespace. generally polluting the global namespace is not advisable, though would work.