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

TypeScript parsing bug - cascading issue with exporting of nihilated TS interface #314

Closed
mprinc opened this issue Aug 4, 2020 · 2 comments

Comments

@mprinc
Copy link

mprinc commented Aug 4, 2020

Hi @evanw,

I just hit an interesting (probably corner case, but popular in my TS projects) where the strategy of nihilating TypeScript interfaces brings inconsistency with the final code. I also built the latest native tool and also tried npm package, with the same result.

Take for example 3 TS files with a.ts -> b.ts -> c.ts dependencies:

c.ts:

export interface IC{
    hello(name:string):string;
}

both esbuild and tsc would eliminate this interface. Good!

b.ts:

export {IC} from './c';

tsc would here parse c.ts as well and understand that it is an interface and remove the export:

// no export

while esbuild will not consult c.ts (it can even not exist :) ) and falsely leave the export:

export {IC} from "./c";

Which hurts JS engine :)

Uncaught SyntaxError: The requested module './c.js' does not provide an export named 'IC'

I just stumbled upon esbuild through snowpack which is affected with this as well.

My current is in their plugin (that uses the esbuild npm package) to prefix on-the-fly (before passing to the esbuild plugin) each exported interface (internal are not an issue) with class with the same name (which will match with not removed export {IC} from "./c";) and prefixing the interface:

export class IC{}; export interface _IC{
    hello(name:string):string;
}

This is the naive solution, but much easier than juggling with dependant TS code in the snowpack context, etc, and it is currently acceptable as I control projects' code and esbuild is not used for production in snowpack anyway (if I am correct?)

@evanw
Copy link
Owner

evanw commented Aug 4, 2020

This isn't really an issue with esbuild. This shouldn't be a problem if you use esbuild as a bundler, for example. It's happening because of the way Snowpack is using esbuild. This will happen with any TypeScript compiler that compiles one file at a time. I believe Babel's TypeScript compiler and even the transpileModule API from the official TypeScript compiler will also do the same thing in this situation. The problem is that just given export {IC} from "./c"; it's impossible to know if IC is a type or a value.

To make sure your code can be compiled with Snowpack, you'll want to add the "isolatedModules": true setting to your tsconfig.json file. That will make the TypeScript compiler turn this kind of code into an error. The specific error you'll get is "Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'". That means to do what you're trying to do in an environment like Snowpack, you need to write your code like this instead:

export type {IC} from './c';

@mprinc
Copy link
Author

mprinc commented Aug 4, 2020

Exactly, great, checked and both transpileModule API and the Babel's TypeScript compiler do the same.

I was not aware of the export type construct (kind of pretty fresh :) ).

Thanks, again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants