6

I've just published my first library package to NPM, and I'm trying to use it in an application project.

It's written in typescript and the project builds okay, and has been published to NPM. But then trying to use it fails as apparently it's not a valid module.

The code in the index.ts file that sets up the module export (afaik) is:

const initByClass = (widgetBindings: WidgetClassBinding[], h: any, render: any) => {
  for (const widgetBinding of widgetBindings) {
    setupWidget(widgetBinding, h, render);
  }
};

module.exports = {
  initByClass
};

And the tsconfig.json file in the library is:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "target": "ES6",
    "module": "ES6",
    "moduleResolution": "node",
    "declaration": true,
    "outDir": "./lib",
    "strict": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/__tests__/*"]
}

In my application code I have added the package to my package.json (and run npm update) and am trying to import it in the app entry file with:

import { initByClass } from "widgety";

but it gives me an error:

TS2306: File '/var/app/app/node_modules/widgety/src/index.ts' is not a module.

What do I need to change, to make the code be importable into another typescript project?

In case they are of use, all of project files: https://github.com/Danack/widgety/ And the NPM package entry: https://www.npmjs.com/package/widgety

4
  • You're using a CommonJS format for your module, but ES6 in your tsconfig. Commented Jun 12, 2020 at 19:52
  • Is CommonJS or ES6 better? Which should I choose, and how would I fix that? Commented Jun 12, 2020 at 19:54
  • If you want to keep the file as is, use "commonjs" for "module" and use require instead of import If you want to use ES6, use export initByClass; or export const initByClass = ... Better? Meh, depends on your audience. If this is to be used in Node, I'd use CommonJS. Otherwise I'd use ES6. Commented Jun 12, 2020 at 19:55
  • Does this answer your question? Typescript es6 import module "File is not a module error" Commented Jun 12, 2020 at 19:57

1 Answer 1

9

A file is considered to be a module when it exports values with the export keyword.

I believe replacing module.exports = with this line, should fix the error:

export default initByClass;

See this documentation: https://www.typescriptlang.org/docs/handbook/modules.html

In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).

Using import or export is what makes the compiler consider a file a module, and assigning to module.exports or using require() does not.

For this reason, and others, always use import and export in typescript codebases.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. That helped, but I also apparently had to change to import initByClass from "widgety";
export const initByClass = ... would allow you to import { initByClass } from '...' if you want to do it that way.
This answer is correct, but I want to know why. Why cant I simply use module.exports

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.