Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Cannot compile namespaces" error with --isolatedModules and no namespaces #15230

Closed
ghost opened this issue Apr 17, 2017 · 54 comments · Fixed by #40032
Closed

"Cannot compile namespaces" error with --isolatedModules and no namespaces #15230

ghost opened this issue Apr 17, 2017 · 54 comments · Fixed by #40032
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging Help Wanted You can do this
Milestone

Comments

@ghost
Copy link

ghost commented Apr 17, 2017

TypeScript Version: nightly (2.3.0-dev.20170417)

Code

function f() {}

Expected behavior:

No error, or an error message about a non-module file in an --isolatedModules project.

Actual behavior:

src/a.ts(1,1): error TS1208: Cannot compile namespaces when the '--isolatedModules' flag is provided.

This occurs because we in program.ts verifyCompilerOptions to look for any source file that isn't an external module declaration, and fail on the first one, whatever it may be.
The error message should be upgraded to reflect the real reason we issue this error, and not mention namespaces.
Alternately, we could just allow files without imports and actually look for a namespace before adding this error.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 17, 2017

The error message needs to be clearer. instead of namespaces it can say non-module. @DanielRosenwasser recommendations?

@mhegazy mhegazy added Bug A bug in TypeScript Help Wanted You can do this Domain: Error Messages The issue relates to error messaging labels Apr 17, 2017
@mhegazy mhegazy added this to the Community milestone Apr 17, 2017
hami9x added a commit to hami9x/TypeScript that referenced this issue May 15, 2017
@hami9x
Copy link

hami9x commented May 15, 2017

There should not be an error message in this situation. The --isolatedModules option should just turn off the internal module system completely, if tsc still errors out this way then the option didn't do its job.

@hami9x
Copy link

hami9x commented May 15, 2017

In #15839 I intended to modify the checking behavior but later realized that this check is just pointless and the ideal solution is to remove it.
Typescript has always allowed usage of namespace inside an external module with --isolatedModules on:

export function something() {} // export found, so this module is considered 'external'
namespace ns {} // namespace is still valid in an external module

Thus the check isn't doing anything in that (seemingly invalid) case, when it's supposed to complain. So why complain when the programmer isn't even using any namespace, doing nothing wrong?

@ghost
Copy link
Author

ghost commented May 15, 2017

@wilonth The reason for this issue is that the error message is wrong: namespaces are perfectly fine if part of a (es6) module, but any non-module file should be an error.

@hami9x
Copy link

hami9x commented May 17, 2017

@andy-ms I was trying to point out that the whole code to check for this error is just pointless, and we should just remove it instead of complicating the code more.
My point is, when --isolatedModules is on, every file should be regarded as an external (ES6) module, period. In that sense, usage of Namespaces should be legal because right now, it is perfectly legal to use Namespaces inside ES6 modules (with --isolatedModules on).

@mhegazy
Copy link
Contributor

mhegazy commented May 18, 2017

My point is, when --isolatedModules is on, every file should be regarded as an external (ES6) module, period.

The semantics here is that a module is a file with at least one top-level import or export. it does not matter how you invoke the compiler.

@hami9x
Copy link

hami9x commented May 19, 2017

@mhegazy Yes and that rule is exactly the root of the problem we have here. The rule unfairly treats a file without import or export as a part of the legacy internal module system, so --isolatedModules rejects the file.
Now we should not change the rule because that will probably break a lot of things, but we can solve the current issue very easily just by removing this error message.
Let's imagine this "cannot compile namespaces" error message being removed, what could go wrong? What about a codebase that uses internal module, like the Typescript compiler itself? With --isolatedModules on, would it compile to garbage code and confuse the user? No it won't, there would be a lot of Typescript error messages about undefined symbols, because --isolatedModules broke the links between the files, pretty obvious to understand.
Can you find ANY downsides with removing this error message? I couldn't. Why wouldn't we choose the easiest solution, that involves zero work (just remove the lines) and has no downsides?

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented May 19, 2017

With --isolatedModules on, would it compile to garbage code and confuse the user? No it won't

Yes, it will.

The point of the --isolatedModules flag is to validate that a program can be successfully compiled through single-file transpilation.

The TypeScript codebase can't be successfully compiled through single-file transpilation. There is code like this everywhere:

file1

namespace ts {
  export var x = 10;
}

file2

namespace ts {
  var y = x; // transpiles to ts.x during whole-program compilation
}

If we single-file transpiled file2, it would break.

@hami9x
Copy link

hami9x commented May 19, 2017

My bad, I screwed up my testing. I hereby retract my proposal. Thank you @RyanCavanaugh for reminding.

@hami9x
Copy link

hami9x commented May 19, 2017

So the solution should be: detect real namespace usage before throwing out this error message (i.e the "alternative" solution that @andy-ms proposed). We can't just change the text to something else because an error message in this case is totally wrong.
I want to make a PR, but can I still be trusted here after spewing out all those bullshit?

@DanielRosenwasser
Copy link
Member

A global file cannot be compiled using '--isolatedModules'. Ensure your file contains imports, exports, or an 'export {}' statement.

@simonbuchan
Copy link

If we single-file transpiled file2, it would break.

Sorry for the necromancy, but surely this should, when targeting modules, fail with something like 'x' is not defined? That case doesn't seem any different to me to the trivial:

file1

var x = 10;

file2

var y = x;

Which also works when concatenating/globally evaluated and not with modules; nothing to do with namespaces.

Essentially, why does typescript bother guessing that files without import or export are not modules, when it should already know from the module compiler option? E.g. Typescript itself compiles without setting module, so it is using the default none, so the compiler can assume concatenation/global evaluation.

When using --module <something> and using un-imported declarations from other files, (including namespaces themselves) typescript will already fail with "not defined" before --isolatedModules, and the same after with the export {} workaround, so this doesn't seem like a compatibility break to remove this guess - am I missing something?

I did notice that for some reason you can still use import/export with --module none --isolatedModules, which is rather confusing, possibly a bug?

@DanielRosenwasser as an end user: what does "A global file" mean? I like the guidance though. Perhaps more like "Files without any import or export statements are not modules, and cannot be compiled with '--isolatedModules'. Add an 'export {}' statement if this file is only evaluated for it's side-effects." - though the language there doesn't seem very error message-y.

@mddheeraj
Copy link

I'm seeing same error for a simple js project. I have just created a sample js project below are the package and script files content. How can I resolve this issue?

Package.json
{
"plnkr": {
"runtime": "system"
}
}

lib/script.js
//
//Blackjack
//by Dheeraj Kumar
//

let card1 = "Ace of spades",
card2 = "ten of Hearts";

console.log('Welcome to Blackjack!');

console.log("You are dealt: ");
conosle.log(" " + card1);
console.log(" " + card2);

@lednhatkhanh
Copy link

Any updates on this?

@shaunluttin
Copy link

I often find myself doing this in small tests.

describe('jest', () => {
  it('finds this test', () => {
    expect(true).toBeTruthy();
  });

  it('parses this typescript', () => {
    const actual: number = 0;
    const expected: number = 0;
    expect(actual).toEqual(expected);
  });
});

export {
  // Use an empty export to please Babel's single file emit.
  // https://github.com/Microsoft/TypeScript/issues/15230
}

@Macil
Copy link

Macil commented Nov 14, 2018

I really want an option that causes TypeScript to consider every .ts file as an ES6 module, regardless of whether it contains import/export statements or not. I originally assumed the --isolatedModules option was that option, but it causes this extremely confusing error on import/export-less files. (I still don't understand what the error message means by namespaces. I don't think I'm using that feature.) The reason I want this setting is because I've had several issues go uncaught by TypeScript because I accidentally referenced a top-level variable from one .ts file in another (which both didn't have import/export statements, so TypeScript didn't treat them as ES6 modules) despite using node/parcel/webpack where files can't reference each other's unexported variables like that.

@jtbennett
Copy link

I wound up here while trying to fix a sort-of-related annoyance. Comments below are just to help any other VS Code users searching about this error with create-react-app and TypeScript.

When configuring a proxy with create-react-app 2.x and TypeScript, you add a file named setupProxy.js with code like this:

const proxy = require('http-proxy-middleware');
module.exports = function(app) { /* ... */ };

react-scripts reads this file outside of the ts transpilation process, so it must be plain js.

This works exactly as documented, but it has an annoying side effect.

The tsconfig.json generated by react-scripts includes all files in src, including setupProxy.js. As a result, it triggers VS Code to show the Cannot compile namespaces... error in setupProxy.js, mark the code with a red squiggle and include it in the Problems pane. In my setup, it also highlights the file and all its ancestor folders in red.

Solution: Suppress the VS Code error message by excluding the setupProxy.js file in tsconfig.json.

{
  // ...
  "exclude": ["src/setupProxy.js"]
}

react-scripts forces isolatedModules: true, but it doesn't appear to overwrite exclude.

Alternative: Add a named export to `setupProxy.js:

export const _ = '';

With a top-level export, it's now valid with --isolatedModules.

@rpokrovskij
Copy link

Very often developers get this message because there are file that should be not included into copliation (gulp.js etc)

@felipedferreira
Copy link

ATTENTION - If you are using a create-react-app and you see this issue like I am... I was able to bypass this by making a change to my tsconfig.json file....

Changing the following

    "isolatedModules": true,

to

    "isolatedModules": false,

@simonbuchan
Copy link

@UncleFifi And then the error moves from the type-check to the babel typescript transform, see the first caveat.

@jtbennett you can just export nothing at all with export {}; - the degenerate form of export { name, localName as exportName };

@Macil
Copy link

Macil commented Jan 29, 2019

@UncleFifi And then the error moves from the type-check to the babel typescript transform, see the first caveat.

Only if you're actually using namespaces. This issue is mainly about this error complaining about namespaces comes up when you're not even using namespaces and just happen to have a legal file with import/export.

@simonbuchan
Copy link

Only if you're actually using namespaces. This issue is mainly about this error complaining about namespaces comes up when you're not even using namespaces and just happen to have a legal file with import/export.

Right, sorry - it's been a while since I read this thread! That said, the reason they set --isolatedModules in CRA is because it closely emulates the limitations of babel typescript (since babel is single-file transpilation too), so you should at least be aware that you are removing that guard-rail.

@Bnaya
Copy link

Bnaya commented Feb 18, 2019

@simonbuchan i've tried all the above before hand - no avail :(

@TomasHubelbauer
Copy link

@simonbuchan Hmm okay so .d.ts works, I can declare the module there and type it. The reason I originally abandoned it is because for those typings I want to declare in that module, I need to reference other typings, but introducing import in the .d.ts file causes it to stop working. I do not know how to resolve this, but that is my lack of TypeScript knowledge which no longer has anything to do with this error.

@yang
Copy link

yang commented Feb 23, 2019

Here's a minimal repro case, using typescript@next (full repo at https://github.com/yang/sandbox-ts-namespaces-error):

src/a.js: (notice, no import/export keywords needed)

module.exports = "hello"; // you could really put anything here, e.g. console.log('hello');

tsconfig.js:

{
  "compilerOptions": {
    "allowJs": true,
    "isolatedModules": true,
    "noEmit": true,
    "strict": true
  },
  "include": ["src"]
}

Error:

$ ./node_modules/.bin/tsc
src/a.js:1:1 - error TS1208: Cannot compile namespaces when the '--isolatedModules' flag is provided.

1 module.exports = "hello";
  ~~~~~~


Found 1 error.

I too first encountered this via create-react-app --typescript, which instructs you to create a setupProxy.js (or setupTests.js). CRA also sets isolatedModules and allowJs to true. It seems to have not been an issue until a more recent typescript version (I didn't see errors about setupProxy.js while on typescript 3.1.x, only after updating to 3.2.x or 3.3.x).

The workaround of adding .js files to your exclude set works when running tsc, but - annoyingly - you still see errors from those files in editors from the TS language service (tried both VS Code and Webstorm). (This seems to be a separate and more general issue with the TS language service not respecting excludes - but I wasn't able to find an existing issue for that.) To mask this error in the editors, I added .d.ts files for the *.js files.

Furthermore, require-ing or import-ing the .js files renders the exclude ineffective as well, causing the error to be raised (outside your editor).

Only disabling allowJs (against what create-react-app suggests) seems to be working for me.

@positonic
Copy link

I keep getting this error for my web worker.

I have tried excluding the individual file or folder and it isn't working for me.

Is there no way to override this isolatedModules setting, CRA keeps rewriting the tsconfig.json.

Any other suggestions?

@Macil
Copy link

Macil commented Mar 4, 2019

@jamespfarrell Put export {}; somewhere in your file.

@positonic
Copy link

@Macil thanks for your advice.

I get this error:

Attempted import error: './workers/HeartBeat.worker.js' does not contain a default export (imported as 'HeartBeatWorker').

If I add:

export default {};

I get:

Uncaught TypeError: workers_HeartBeat_worker_js__WEBPACK_IMPORTED_MODULE_2_.default is not a constructor

@positonic
Copy link

Isn't there simply a way to bypass this 'isolatedModules' if not for one file, even for all files?

@Macil
Copy link

Macil commented Mar 4, 2019

Those errors you're getting now are unrelated to the isolatedModules setting. If you turned off isolatedModules, you'll still get those errors.

Attempted import error: './workers/HeartBeat.worker.js' does not contain a default export (imported as 'HeartBeatWorker').

Where is this error happening? It sounds like you're trying to import the default export of a file that doesn't have one, like import Foo from './workers/HeartBeat.worker.js';. If you don't want to import a default export, then change your import line to import './workers/HeartBeat.worker.js';.

@positonic
Copy link

You're right it was something else @Macil ! thanks!

@VyvIT
Copy link

VyvIT commented Mar 5, 2019

Maybe somebody else will have the same issue: I had the same error appearing for a few files I've left as placeholders with no content in them but I've been importing them in other files, ie. I had empty styles.js file which was imported in another component file.

@DaviSpindola
Copy link

Just add
image

@coffenbacher
Copy link

coffenbacher commented Apr 16, 2019

I had this error for a module definition that I accidentally suffixed .ts instead of .d.ts, if anyone else is making that particular mistake. Have to restart server after fixing.

@MatteoGioioso
Copy link

MatteoGioioso commented Apr 20, 2019

Same error. I am using CRA

@negamaxi
Copy link

Faced this issue on CRA. I was simply forget to export anything from the file:
Снимок экрана от 2019-04-22 22-24-04

@thitemple
Copy link

So I had this error because I had a .js file in the root folder of my project, in my tsconfig.json file I had this configured:

"compilerOptions": {
    ....
  },
  "include": ["src"],

I had to switch it for this:

"compilerOptions": {
    ....
  },
  "include": ["src/*"],

That fixed it, but I don't understand why, can someone explain it to me? My understanding was that including src would eliminate root files and sibling folders.

@vort3xxx
Copy link

@thitemple Did you get that /* snippet from an article somewhere? The webpack manual seems to indicate that the first one is the correct one. I'm diagnosing a similar problem and came across your post.

@thitemple
Copy link

@vort3xxx I did not. I saw this post #15230 (comment) from @DaviSpindola and tried it. That was it

@kdmadej
Copy link

kdmadej commented Aug 27, 2019

@vort3xxx I did not. I saw this post #15230 (comment) from @DaviSpindola and tried it. That was it

Same problem, same solution. TS 3.5.2.

@55Cancri
Copy link

55Cancri commented May 13, 2020

@ThomasdenH

@simonbuchan I tried a .d.ts but that didn't work for me either, I will report back with why exactly, not sure what it was. And indeed CRA rewrote that setting for me.

Encountering the exact same issue. Did you ever figure out how to solve this? Defining .ts or .d.ts declaration files inside of a create react app returns the error All files must be modules when the '--isolatedModules flag is provided. Setting the flag to false or removing the isolatedModules property entirely resets to true when starting create react app.
Adding export {} at the bottom of the declaration file results in the error: Invalid module name in augmentation. Module '...' resolves to an untyped module at '...'.

Someone please help. How do I add custom declaration files to a create react app project?

@55Cancri
Copy link

55Cancri commented May 13, 2020

Just figured it out if anyone else is having the same issue. Simply add your declaration types to the react-app-env.d.ts file in the source folder when using create react app.

@Arisono
Copy link

Arisono commented Sep 27, 2021

问题得到解决,查看文章:https://blog.csdn.net/qingfeng812/article/details/120510673
If the problem is solved, check the article https://blog.csdn.net/qingfeng812/article/details/120510673

@Guvidaletti
Copy link

If you're trying to test, you could just add this to your tsconfig.json.

...
"exclude": ["src/test"],
...

and put all your tests in that folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging Help Wanted You can do this
Projects
None yet