Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TS2351: How to create constructor typings for `new function()` in ts

Tags:

typescript

I'm creating a npm package, that exports default a class. This module is written in es3, but I want to provide types.ts

index.js (in my package)

function MyClass(p1, p2) {
  // code
}

module.exports =  MyClass;

Ok, then I created types index.d.ts (inside my package, aside index.js):

declare module 'mypackageid' {
  interface MyClass {
    new (div: HTMLElement, conf: any): MyClass;
  }
  export var MyClass: MyClass;
}

I can easily use this code in es3 and it works. (outside of my package, e.g. from another package)

var myInstance = new MyClass()

But if I want to use it from another package inside of .ts file:

import MyClass from 'mypackageid';

new MyClass(divReference, { // <-- error points to this line
    onBlobPaste: e=> {
      console.log(e);
    },
});

Typescript loader refuses to compile and prints:

TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

EDIT 1:

You use a commonjs default export in your .ts file, your .d.ts file specifies a member export, and your consumer is expecting an ES6 default export. In what way are you actually trying to export it? You have to pick one

I don't explicitly import types, I expect typescript to autodetect types automagically from 'index.d.ts'. If I use default export like this:

declare module 'mypackageid' {
  interface MyClass {
    new (div: HTMLElement, conf: any): MyClass;
  }
  export default MyClass
}

I will get error below. The error points to line with new

S2693: 'MyClass' only refers to a type, but is being used as a value here.

like image 732
deathangel908 Avatar asked Jul 05 '18 23:07

deathangel908


1 Answers

If you use the exports= approach in you module, and thus replace the whole export of your module, you will need to use import=, and a module system that supports this (such as AMD or commonjs). See docs

mypackageid.d.ts
declare module 'mypackageid' {
    class MyClass {
        constructor(div: HTMLElement, conf: any);
    }
    export = MyClass;
}


//Usage
import MyClass = require('mypackageid')

new MyClass(null, null)

Also if you want to use an interface with new, that can't be the export (as it is a type) you need to declare a const and export that:

declare module 'mypackageid' {
    interface MyClassCtor {
        new (div: HTMLElement, conf: any) : {};
    }
    const MyClass : MyClassCtor;
    export = MyClass;
}
like image 82
Titian Cernicova-Dragomir Avatar answered Nov 17 '22 05:11

Titian Cernicova-Dragomir