Typescript: Crash tsc --watch on adding "module": "none" to tsconfig

Created on 14 Jul 2020  Â·  13Comments  Â·  Source: microsoft/TypeScript

$ tsc --version
Version 4.0.0-dev.20200714

```
$ tsc --showconfig
{
"compilerOptions": {
"target": "es2018",
"strict": true,
"skipLibCheck": true
},
"files": [
"./test.ts"
]
}


This is **only** an issue on `4.0.0`, this was not happening on `3.9.6`

<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
empty export 
**Code**
```ts
import type { foo } from './bar'
const a: foo = {};

// Test this by running tsc on the command-line, rather than through another build tool such as Gulp, Webpack, etc.

Expected behavior:
output should be

const a = {};

Actual behavior:

const a = {}
export {};

Playground Link:

Related Issues:

Bug

All 13 comments

This is intentional change #38696 and PR #38712

Used same search terms "empty export"

It breaks code.
I have to manually go into the file and remove it because the browser cannot run the file.
@IllusionMH ahh, it seems the two things you linked too are "closed" issues and github slapped on the 'open' filter without it asking me too and I didn't realise

You should specify proper module option in tsconfig.json according to your needs.

Or use <script type="module" src="..."></script> in HTML to use ES2015 modules as is.


There is is:open filter in search field, so I usually just remove it when looking for duplicates

There is is:open filter in search field, so I usually just remove it when looking for duplicates

@IllusionMH yes, as I said, I didn't notice it added it.

I tried doing "module": "none". it crashed the compilar due to another bug with

...\typescript\lib\tsc.js:10246
        return !!(module.flags & 1024);
                         ^
TypeError: Cannot read property 'flags' of undefined
    at Object.isGlobalScopeAugmentation (...\typescript\lib\tsc.js:10246:26)

This is why I supplied NO module config at all.. And expect to get NO module/export stuff at all..

Which works in 3.9 but 4.0 breaks

Seems the above error is only a problem when using tsc --watch,
Sadly, when I use tsc it STILL injects broken code with modules: none because it adds the line

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

Which "exports" is undefined, so the code doesn't run.
I used esModuleInterop: false but it still adds it. So the code is broken..

Basically, it means 4.0.0 will leave the javascript with unrunable code.

Sadly, when I use tsc it STILL injects broken code with modules: none because it adds the line

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

This is behavior from 3.8 when import type was introduced. Maybe @andrewbranch can tell if it's expected behavior for "module": "none".

@andrewbranch see crash report mid-thread

There are three separate things to address here:

  1. The crash with module: none obviously needs to be fixed.

  2. It turns out that with target >= es2015 and --module=none, we don’t issue errors on any kind of imports/exports. You _should_ get the error Cannot use imports, exports, or module augmentations when '--module' is 'none'.

  3. This leaves the less obvious question of whether type-only imports should be a special exception to that error since they don’t emit. My stance is they should not. As I explained in the original type-only imports PR, import type marks a file as a module, which doesn’t make sense in a --module=none compilation. If you’re targeting the browser directly, your implementation files should be scripts, and anything that makes them interpreted as modules will give you misleading checking behavior, so we should prevent you from accidentally doing that.

    To solve your particular problem, you should write const a: import("./bar").foo = {}.

Would

type foo = import("./bar").foo;

const a: foo = {};
const b: foo = {};

Be acceptable in this situation?
In a real world file I would have multiple places referencing the same type?

Yep, that works! Just be aware that just like a and b are visible as globals in this example, foo is too.

That should work.

Just in case if foo is generic - you'll need to recreate generic params in your new type declaration

type foo<T> = import('./bar').foo<T>;

Yep, that works! Just be aware that just like a and b are visible as globals in this example, foo is too.

Okay, that is an interesting complication. Thankfully for my current use case that is not a problem, but may perceive multiple files working as one each having reference to type foo in the future.

But that is Future Colin's problem!
Thank you for your help.

That should work.

Just in case if foo is generic - you'll need to recreate generic params in your new type declaration

type foo<T> = import('./bar').foo<T>;

Ohhh. Didn't know about that little hickup. I will keep that in mind.
Thankfully this is not how we usually do stuff in our codebase, this is a one off tool (hack) that has a life expectancy of 3 weeks, so I hopefully won't have to deal with that .

@andrewbranch @IllusionMH
Just wanted to say thank you.

type foo = import("./bar").foo;

and

"module": "none"

worked perfectly.. (of course except for --watch, but I can live with that)
again, Thank you

edit just noticed you fixed the --watch so I installed typescript@next and can confirm it works SUPER perfectly now..

Was this page helpful?
0 / 5 - 0 ratings