tarling
tarling

Reputation: 1957

How write declaration for class and namespace with same name in Typescript

I'm using a 3rd party Javascript library in this format:

var MyClass = function (name) {
    this.name = name;
}

MyClass.prototype.greet = function () {
    window.alert('Hello ' + this.name)
}

I want to write a Typescript declaration for this. I've got this sort of thing:

declare class MyClass {
    constructor(name: string);
    greet(): void;
}

This is all compiling fine and when I just want to refer to the types it is working as expected. But I'm having problems trying to use the class implementation.

Using it this way, it compiles and runs, but I get no compile time checking

const MyClass = (require('./MyClass') as any).MyClass;
const a = new MyClass('Bob'); //a is any

Using it this way I get a compiler error

const MyClass = (require('./MyClass') as any).MyClass as MyClass;
const a = new MyClass('Bob'); //Cannot use 'new' with an expression whose type lacks a call or construct signature.

Using it this way I get a compiler error

import './MyClass';
const a = new MyClass('Bob');
//duplicate identifier in MyClass.d.ts

Upvotes: 5

Views: 3668

Answers (2)

Mike Lippert
Mike Lippert

Reputation: 2261

So the first problem is that your declaration file is for the MyClass module and defines the class but doesn't describe that modules exports. The second problem is that you then need the matching import statement in your main module. import './MyClass' is only to import side effects (see the typescript modules doc.

Based on the code that works, it looks like the MyClass module exports an object with a MyClass property (set to the MyClass class) so that's what I've added to your declaration file.

The MyClass.d.ts declaration file for the js module:

declare class MyClass {
  constructor(name: string);
  greet(): void;
}

export { MyClass }

Then in your main.ts:

import { MyClass } from './MyClass';

let a = new MyClass('foo');
a.greet();

Upvotes: 2

robkuz
robkuz

Reputation: 9934

I would try something like this

declare class MyClass {
    greet(): void;
}

declare type MyClassFactory = (x: string) => MyClass

const factory = (require('./MyClass') as any).MyClass as MyClassFactory;
const a = factory('Bob');

which is to detach the class and its constructor function

Upvotes: 1

Related Questions