Home > OS >  How to properly import a class definition from a module in typescript?
How to properly import a class definition from a module in typescript?

Time:12-30

I'm trying to use the AsyncAPI Generator in my typescript application. The generator is a commonjs module which is giving me some grief.

import { Generator } from '@asyncapi/generator';

const generator = new Generator('@asyncapi/html-template', './test');

I've created my own type definition for the generator as there are no types provided by the library itself.

declare module '@asyncapi/generator' {
  class Generator {
    constructor(templateName: string, targetDir: string, options?: any);
    // more method definitions
  }
}

The code seems to compile fine, but at runtime I get the following error: TypeError: generator_1.Generator is not a constructor. When I build my project and inspect the generated javascript code I see what the issue is. The typescript code is compiled as follows.

const generator_1 = require("@asyncapi/generator");
const generator = new generator_1.Generator('@asyncapi/html-template', './test');

A plain javascript example that works fine for me shows the difference.

const Generator = require('@asyncapi/generator');
const generator = new Generator('@asyncapi/html-template', './test');

I understand why I get the error. The library exports the class definition itself, but I can't figure out how to correctly import it in my typescript code.

class Generator {
  // constructor and method definitions
}

module.exports = Generator;

Any suggestions would be greatly appreciated!

CodePudding user response:

The equivalent to:

const Generator = require('@asyncapi/generator');

with the ESM import syntax is

import Generator from '@async/generator';

this is called a default export.

Your TypeScript definition doesn't match the JavaScript package and this causes the TypeError.

There are multiple ways to define this type, one way is:

declare module "@asyncapi/generator" {
  export default class Generator {
    constructor(templateName: string, targetDir: string, options?: any);
    // more method definitions
  }
}

This requires you to set esModuleInterop to true in your tsconfig.json:

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

See https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html

  • Related