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;
}
}
I try to import it into my project like this:
import IEmitter = require('emitter20')
export interface SwapManager extends IEmitter {
manager: any;
}
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.
How do I define and import the type definition for the emitter20
module?
(Aside: Typescript imports/exports... one hell of a learning curve!)
The problem here is that this is not a "proper" JS module and be warned that it doesn't actually expose any types per se, so you will not be able to subclass it... I think.
If this was a "normal"(?) or ES6 JS module which returned classes, etc you would be able to just simply use a bunch of export this; export that; export default function factory()
like you tried, but this is one of those modules that are a function and export =
is used in my approach which is documented as:
For backwards compatibility with CommonJS and AMD style modules, TypeScript also supports export-equals declarations of the form export = Point. Unlike default export declarations, which are just shorthand for an export named default, export-equals declarations designate an entity to be exported in place of the actual module.
I know of the following two approaches to get this "typed":
Pros:
Cons:
main.ts
import * as emitterFactory from 'emitter20';
var emitterInstance = emitterFactory();
emitterInstance.on(...)
types.d.ts
declare module 'emitter20' {
interface IEmitter {
on: (eventName: string, cb: (data?: any) => void) => void;
trigger: (eventName: string, data?: any) => void;
}
interface IEmitterFactory {
(): IEmitter;
}
var EmitterFactory : IEmitterFactory;
export = EmitterFactory;
}
Pros:
Cons:
main.ts
import * as emitter from 'emitter20';
var emitterInstance : emitter.IEmitter = emitter();
emitterInstance.on("event", (data : any) => {
console.log(data.foo);
})
emitterInstance.trigger("event", {"foo": "bar"});
Output:
bar
types.d.ts
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;
}
Pros:
Cons:
Emitter
namespace becomes global and visible everywhere (global ambient declaration)main.ts
import * as emitter from 'emitter20';
var emitterInstance : Emitter.IEmitter = emitter();
types.d.ts
declare namespace Emitter
{
export interface IEmitter {
on: (eventName: string, cb: (data?: any) => void) => void;
trigger: (eventName: string, data?: any) => void;
}
export interface IEmitterFactory {
(): Emitter.IEmitter;
}
}
declare module 'emitter20' {
var EmitterFactory : Emitter.IEmitterFactory;
export = EmitterFactory;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With