user6600549
user6600549

Reputation:

Typescript ReferenceError: exports is not defined

Trying to implement a module following the official handbook, I get this error message:

Uncaught ReferenceError: exports is not defined

at app.js:2

But nowhere in my code do I ever use the name exports.

How can I fix this?


Files

app.ts

let a = 2;
let b:number = 3;

import Person = require ('./mods/module-1');

module-1.t

 export class Person {
  constructor(){
    console.log('Person Class');
  }
}
export default Person;

tsconfig.json

{
   "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "noImplicitAny": false,
        "sourceMap": true,
        "outDir": "scripts/"
    },
    "exclude": [
        "node_modules"
    ]
}

Upvotes: 284

Views: 643882

Answers (30)

Masih Jahangiri
Masih Jahangiri

Reputation: 10897

Remove "type": "module" from package.json.

Upvotes: 99

Zakariae BEN ALLAL
Zakariae BEN ALLAL

Reputation: 92

Hello o fix this probleme by using this :

{
  "compilerOptions": {
    "target": "es6",  // 👈️ set this to es6
    // "module": "commonjs", // 👈️ REMOVE this (if browser env)
  }
}

Upvotes: 0

Steven Scaffidi
Steven Scaffidi

Reputation: 2307

If you are are using webpack along with babel-loader and @babel/preset-env, then make sure to callout loose and modules. So instead of the following:

"presets": ["@babel/preset-env"]

instead do

"presets": [["@babel/preset-env", { "loose": true, "modules": false }]],

Upvotes: 2

vharron
vharron

Reputation: 1207

I hit this error shortly after switching to "Node 16 + ESM + strict" tsconfig.json.

I think the ESM change was the bit that caused it.

I had to bisect the file to figure out the root cause:

exports.webhookTaskProcessor = functions.firestore
  .document("items/{itemId}/tasks/{taskId}")
  .onCreate((_change, context) => {
    processItemTasks(context.params.itemId);
  });

This fixed it:

export const webhookTaskProcessor = functions.firestore
  .document("items/{itemId}/tasks/{taskId}")
  .onCreate((_change, context) => {
    processItemTasks(context.params.itemId);
  });

Would be rad if the error message was a little more helpful. I hope this breadcrumb is useful to you.

Upvotes: 3

TaSvet
TaSvet

Reputation: 442

I have this issue too. then I just change "module": "commonjs" to "module": "ESNext" everything is working fine.
this my tsconfig.json:

{
    "compilerOptions": {
      "module": "ESNext",
      "esModuleInterop": true,
      "target": "ESNext",
      "moduleResolution": "node",
      "sourceMap": true,
      "outDir": "dist",
    },
    "lib": ["ESNext"],
  }

I hope it can solve your problem!

Upvotes: 4

Spencer Davis
Spencer Davis

Reputation: 171

In package.json, add "type": "module"

In terminal type in

npx tsc --init

It will create a tsconfig.json.

In tsconfig.json,

  1. change "target": "es5" to "target": "es6"
  2. comment out //"module": "commonjs",
  3. uncomment "moduleResolution": "node",

You should be good to go.

In package.json, create a build script:

"build": "tsc -p tsconfig.json"

Then, when you want to build, you just compile npm run build

then execute and should be good

Upvotes: 7

kydreth
kydreth

Reputation: 81

So this is a super generic TypeScript error and this StackOverflow question is the first result for various queries I made researching my problem. It has 385k views.

For those with Angular / TypeScript and an Angular Library using ng-packagr seeing a generic "ReferenceError: exports is not defined", you'll need to define public-api.ts for each feature/component/service such that you include it with index.ts such as found in this repo for this article

  • Node 16 or 18 (18 is LTS next week)
  • Angular 2+ (14 currently)
  • TypeScript 4.6.4-4.8.2

Several shallow examples go something like this referencing Creating Libraries

ng new workspace --no-create-application
cd workspace
ng generate app home --routing=true --style=scss
ng generate app admin --routing=true --style=scss
ng generate library lib
... # include your library 'lib' into your application 'home'
ng build lib --watch &
ng serve home --open

What's not directly explained is your index.ts and public-api.ts files need to be in each feature/component/service. Such as these example features A, B, and C in the repo below if you have a complex library. repo has the following:

  • src/lib
    • feature-a
      • index.ts (referencing only ./public-api)
      • public-api.ts (referencing only exported files in the directory)
    • feature-b
      • index.ts (referencing only ./public-api)
      • public-api.ts (referencing only exported files in the directory)
    • feature-c
      • index.ts (referencing only ./public-api)
      • public-api.ts (referencing only exported files in the directory)

Upvotes: 1

sudo
sudo

Reputation: 386

Not answering the question directly, but no stackoverflow thread mentionned this case, took me a while to debug, and so adding it here in case it could help someone in the future.

I had the error "exports is not defined" coming from an imported NPM module. Changing my typescript config did nothing as I had no control over the imported third-party code. The problem was an invalid import syntax for that package. For example, I had imported "@mui/material/TextField/TextField", yet the correct import was supposed to be "@mui/material/TextField".

Upvotes: 1

Venkatesh Muniyandi
Venkatesh Muniyandi

Reputation: 5630

Add the following line before other references to JavaScript. This is a nice little hack.

<script>var exports = {};</script>

Upvotes: 132

Gass
Gass

Reputation: 9326

First, go to your index.html in your public folder find the reference of the script <script src="myScript.js"></script> and add type="module"

Like so:

<script type="module" src="myScript.js"></script>

Secondly, in your tsconfig.json make sure target is set to es5 and module to es2015

 "compilerOptions": {
    "target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    /* Modules */
    "module": "es2015", /* Specify what module code is generated. */
}

important: make sure to import with the .js extension e.g. import Piece from './classes/piece.js'

Upvotes: 3

Jivik
Jivik

Reputation: 31

I think the problem may be the mismatched configuration.

  1. Working solution 1 below give you a correct configuration for ES Module.
  2. Working solution 2 below give you a correct configuration for CommonJS.
  3. Mixed solution 1+2 give you an Error.

I just post partial content here, for clarity. Github project https://github.com/jmmvkr/ts-express/ have a complete set of files demonstrate the working solution 1 and solution 2.

Working solution 1, ES Module

/* Configuration for ES Module */

// tsconfig.json
{
    "compilerOptions": {
        "module": "es6", // or "esnext"
    }
}
// package.json
{
    "type": "module", // type is module
}

Working solution 2, CommonJS

/* Configuration for CommonJS */

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
    }
}
// package.json
{
    "type": "", // type is NOT module
}

Mixed, do NOT work

/* Mixed, got ReferenceError: exports is not defined in ES module scope */

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
    }
}
// package.json
{
    "type": "module", // type is module
}

Upvotes: 2

mhanley00
mhanley00

Reputation: 729

I ran into this issue a few weeks ago and used the exports hack above in the short term but finally figured out another way around this that's working great for me.

So unlike some of the other responses above, I actually wanted the code I'm compiling to be a module. By setting "target": "es6", "module": "esnext" and then linking to my compiled JS file with type="module" instead of type="text/javascript", my compiled code no longer has the Object.defineProperty(exports, "__esModule", { value: true }); line and it's still a module 🎉

My tsconfig:

{
  "compilerOptions": {
    "target": "es6",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "esnext",
    "moduleResolution": "node",
    "lib": ["es2016", "esnext", "dom"],
    "outDir": "build",
    "strict": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
  },
  "include": ["src/index.ts"],
  "exclude": ["build"]
}

My link to my compiled code in HTML head tags:

<script src="../build/index.js" type="module" defer></script>

As a bonus, now I can also import anything that I export in that index.js file in a separate type="module" script down below the main HTML body code:

 <script type="module">
   import { coolEncodingFunction, coolDecodingFunction } from "../build/index.js";
   /* Do stuff with coolEncodingFunction and coolDecodingFunction */
   /* ... */
</script>

Upvotes: 19

Krunal Shah
Krunal Shah

Reputation: 171

I had similar issue as the original poster of the question:

I better tell you what mistakes I made and how I corrected it, that might help someone.

I had javascript nodejs project and converted it to typescript.

Previously in package.json I had "type":"module" when I was running in JavaScript.

When I converted it to TypeScript project and started converting files in .ts files and started running using following command:

npx tsc test.ts && node test.ts

I would get the above error.

I got rid of the error by simply removing the "type":"module" from package.json

My tsconfig.json would like below:

{
    "compilerOptions": {
        "target": "esnext",
        "lib": ["es6", "es5", "es7", "dom"],
        "allowJs": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "es6",
        "outDir": "./build",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "skipLibCheck": true
    },
    "exclude": ["node_modules", "build"]

I am using node 14 and TypeScript 4.2.4

Upvotes: 4

User Rebo
User Rebo

Reputation: 4580

As ES5/ES2009 doesn't support modules (import/export/require) on the client / browser you have to use libraries, which bundle the modules into a single file, which can be included via <script> tag, such as

See also this answer.

Upvotes: 0

Alex Po
Alex Po

Reputation: 2035

I stuck with such error in a SSR client part because it used a lib which was built with tsconfig.json compilerOptions as target: ES5 what brought using CommonJS for module resolution tsc CLI Options Compiler Options: target === "ES3" or "ES5" ? "CommonJS" : "ES6". While it used the target ESNext.

Upvotes: 0

iFreilicht
iFreilicht

Reputation: 14464

EDIT:

This answer might not work depending if you're not targeting es5 anymore, I'll try to make the answer more complete.

Original Answer

If CommonJS isn't installed (which defines exports), you have to remove this line from your tsconfig.json:

 "module": "commonjs",

As per the comments, this alone may not work with later versions of tsc. If that is the case, you can install a module loader like CommonJS, SystemJS or RequireJS and then specify that.

Note:

Look at your main.js file that tsc generated. You will find this at the very top:

Object.defineProperty(exports, "__esModule", { value: true });

It is the root of the error message, and after removing "module": "commonjs",, it will vanish.

Upvotes: 125

Matt
Matt

Reputation: 2290

If you are just using interfaces for types, leave out the export keyword and ts can pick up on the types without needing to import. They key is you cannot use import/export anywhere.

export interface Person {
   name: string;
   age: number;
}

into

interface Person {
   name: string;
   age: number;
}

Upvotes: -2

Rupesh Shitole
Rupesh Shitole

Reputation: 31

To solve this issue, put these two lines in your index.html page.

<script>var exports = {"__esModule": true};</script>
<script type="text/javascript" src="/main.js">

Make sure to check your main.js file path.

Upvotes: 2

Doug Wilhelm
Doug Wilhelm

Reputation: 796

I had the same issue, but my setup required a different solution.

I'm using the create-react-app-rewired package with a config-overrides.js file. Previously, I was using the addBabelPresets import (in the override() method) from customize-cra and decided to abstract those presets to a separate file. Coincidentally, this solved my problem.

I added useBabelRc() to the override() method in config-overrides.js and created a babel.config.js file with the following:

module.exports = {
    presets: [
        '@babel/preset-react',
        '@babel/preset-env'
    ],
}

Upvotes: 0

Carlos Alves
Carlos Alves

Reputation: 1

  {
    "compileOnSave": false,
    "compilerOptions": {
      "baseUrl": "./",
      "outDir": "./dist",
      "sourceMap": true,
      "declaration": false,
      "module": "esnext",
      "moduleResolution": "node",
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "target": "es5",
      "typeRoots": ["node_modules/@types"],
      "lib": ["es2018", "dom"]
    }
  }

Upvotes: -3

Arpan Srivastava
Arpan Srivastava

Reputation: 380

Note: This might not be applicable for OP's answer, but I was getting this error, and this how I solved it.

So the problem that I was facing was that I was getting this error when I retrieved a 'js' library from a particular CDN.

The only wrong thing that I was doing was importing from the CDN's cjs directory like so: https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/cjs/popper.min.js

Notice the dist/cjs part? That's where the problem was.

I went back to the CDN (jsdelivr) in my case and navigated to find the umd folder. And I could find another set of popper.min.js which was the correct file to import: https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js.

Upvotes: 2

Pat
Pat

Reputation: 443

Had the same issue and fixed it by changing the JS packages loading order.

Check the order in which the packages you need are being called and load them in an appropriate order.

In my specific case (not using module bundler) I needed to load Redux, then Redux Thunk, then React Redux. Loading React Redux before Redux Thunk would give me exports is not defined.

Upvotes: 0

Code Whisperer
Code Whisperer

Reputation: 23654

This is fixed by setting the module compiler option to es6:

{
  "compilerOptions": {     
    "module": "es6",
    "target": "es5",    
  }
}

Upvotes: 53

user3033599
user3033599

Reputation: 57

for me, removing "esModuleInterop": true from tsconfig.json did the trick.

Upvotes: 3

Daniel Danielecki
Daniel Danielecki

Reputation: 10502

Simply add libraryTarget: 'umd', like so

const webpackConfig = {
  output: {
    libraryTarget: 'umd' // Fix: "Uncaught ReferenceError: exports is not defined".
  }
};

module.exports = webpackConfig; // Export all custom Webpack configs.

Upvotes: 2

duliba
duliba

Reputation: 279

Try what @iFreilicht suggested above. If that didn't work after you've installed webpack and all, you may have just copied a webpack configuration from somewhere online and configured there that you want the output to support CommonJS by mistake. Make sure this isn't the case in webpack.config.js:

module.exports = {
  mode: process.env.NODE_ENV || "development",
  entry: { 
    index: "./src/js/index.ts"
  },
  ...
  ...
  output: {
    libraryTarget: 'commonjs',         <==== DELETE THIS LINE
    path: path.join(__dirname, 'build'),
    filename: "[name].bundle.js"
  }
};

Upvotes: 0

CPHPython
CPHPython

Reputation: 13699

For some ASP.NET projects import and export may not be used at all in your Typescripts.

The question's error showed up when I attempted to do so and I only discovered later that I just needed to add the generated JS script to the View like so:

<script src="~/scripts/js/[GENERATED_FILE].Index.js" asp-append-version="true"></script>

Upvotes: 1

MatX
MatX

Reputation: 106

I had this same error too. In my case it was because we had an old-fashioned import statement in our TypeScript AngularJS project like this:

import { IAttributes, IScope } from "angular";

which was compiled to JavaScript like this:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

This was needed back in the old days because we then used IAttributes in the code and TypeScript wouldn't have known what to do with it otherwise. But after removing the import statement, and converting IAttributes to ng.IAttributes those two JavaScript lines disappeared - and so did the error message.

Upvotes: 5

Hocine Abdellatif Houari
Hocine Abdellatif Houari

Reputation: 1105

my solution is a sum up of everything above with little tricks I added, basically I added this to my html code

<script>var exports = {"__esModule": true};</script>
<script src="js/file.js"></script>

this even allows you to use import instead of require if you're using electron or something, and it works fine with typescript 3.5.1, target: es3 -> esnext.

Upvotes: 11

Yi Zhang
Yi Zhang

Reputation: 335

npm install @babel/plugin-transform-modules-commonjs

and add to to .babelrc plugins resolved my question.

Upvotes: 21

Related Questions