Typescript ReferenceError: exports is not defined
TypescriptModuleTypescript Problem Overview
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"
]
}
Typescript Solutions
Solution 1 - Typescript
Few other Solutions for this issue
- Add the following line before other references to Javascript. This is a nice little hack.
<script>var exports = {};</script>
Solution 2 - Typescript
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.
Solution 3 - Typescript
A solution:
Remove "type": "module"
from package.json
.
Solution 4 - Typescript
This is fixed by setting the module
compiler option to es6
:
{
"compilerOptions": {
"module": "es6",
"target": "es5",
}
}
Solution 5 - Typescript
npm install @babel/plugin-transform-modules-commonjs
and add to to .babelrc plugins resolved my question.
Solution 6 - Typescript
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.
Solution 7 - Typescript
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>
Solution 8 - Typescript
I had the same problem and solved it adding "es5" library to tsconfig.json like this:
{
"compilerOptions": {
"target": "es5", //defines what sort of code ts generates, es5 because it's what most browsers currently UNDERSTANDS.
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true, //for angular to be able to use metadata we specify in our components.
"experimentalDecorators": true, //angular needs decorators like @Component, @Injectable, etc.
"removeComments": false,
"noImplicitAny": false,
"lib": [
"es2016",
"dom",
"es5"
]
}
}
Solution 9 - Typescript
For people still having this issue, if your compiler target is set to ES6 you need to tell babel to skip module transformation. To do so add this to your .babelrc
file
{
"presets": [ ["env", {"modules": false} ]]
}
Solution 10 - Typescript
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.
Solution 11 - Typescript
for me, removing "esModuleInterop": true
from tsconfig.json did the trick.
Solution 12 - Typescript
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
Solution 13 - Typescript
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.
Solution 14 - Typescript
in package.json add in
"type": "module"
in terminal type in
npx tsc --init
it will create a tsconfig.json
change
"target": "es5"
to
"target": "es6"
comment out
//"module": "commonjs",
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
Solution 15 - Typescript
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>
Solution 16 - Typescript
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
.
Solution 17 - Typescript
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.
Solution 18 - Typescript
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"
}
};
Solution 19 - Typescript
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
.
Solution 20 - Typescript
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'
],
}
Solution 21 - Typescript
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
.
Solution 22 - Typescript
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.
Solution 23 - Typescript
I think the problem may be the mismatched configuration.
- Working solution 1 below give you a correct configuration for ES Module.
- Working solution 2 below give you a correct configuration for CommonJS.
- 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
}
Solution 24 - Typescript
{
"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"]
}
}
Solution 25 - Typescript
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;
}