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

New @babel/parser early errors break by-name typescript exports #9763

Closed
Jessidhia opened this issue Mar 25, 2019 · 7 comments · Fixed by #9766 or #9944

Comments

@Jessidhia
Copy link
Member

commented Mar 25, 2019

Bug Report

Current Behavior
@babel/parser doesn't consider identifiers declared with typescript syntax as identifiers in scope.

Input Code

enum Test {}

export { Test as default }

Expected behavior/code
exports of typescript types should not be a build error.

This case is particularly strange as Test is actually a concrete value; it's just declared with a typescript declaration.

This is the expected output, for reference:

var Test;

(function (Test) {})(Test || (Test = {}));

export { Test as default }

Direct export enum Test {} is unaffected.

Babel Configuration (.babelrc, package.json, cli command)

Way too big, but just adding @babel/plugin-syntax-typescript to the REPL is sufficient to reproduce it. @babel/plugin-transform-typescript doesn't help as the error happens before any transforms can run.

Environment

  • Babel version(s): 7.4.2
  • Node/npm version: 11.10.0
  • OS: macOS 18.2.0
  • Monorepo: yes
  • How you are using Babel: babel-jest / babel-loader

Possible Solution
Identifiers declared with type, enum, interface (and namespace) need to be considered as valid for exporting when the typescript plugin is enabled.

This same problem affects flow but the other way around. The following code is "valid syntax" in both flow and typescript; but babel can only parse the flow version, which is incorrect at runtime as flow requires explicitly annotating the export as a type export:

type Foo = {}
export { Foo }
@Jessidhia

This comment has been minimized.

Copy link
Member Author

commented Mar 25, 2019

Tangentially related: @babel/traverse doesn't seem to track typescript identifiers on Scope at all.

Maybe it's some kind of missing @babel/types alias?

@benmosher

This comment has been minimized.

Copy link
Contributor

commented Mar 25, 2019

I am also seeing this with function overloads. Here's a repro (same code also below) -- you also have to explicitly add the typescript syntax plugin or it errors on syntax instead.

// commenting the following overload signature resolves the issue?
export function flatten<V>(
  iterable: Iterable<V | Iterable<V>>,
): IterableIterator<V>

export function* flatten(iterable: Iterable<any>): IterableIterator<any> {
  for (let item of iterable) {
    if (isIterable(item)) yield* item
    else yield item
  }
}

export function chain(
  ...iterables: (any | Iterable<any>)[]
): IterableIterator<any> {
  return flatten(iterables)
}

export { chain as concat }

output:

/repl: Export 'chain' is not defined (19:9)

  17 | }
  18 | 
> 19 | export { chain as concat }
     |          ^
  20 | 

Also weird: export { flatten as concat } works fine. So I'm not able to intuit what is going on. Also this worked fine 2 hours ago before I regenerated my yarn.lock. 😅

@nicolo-ribaudo nicolo-ribaudo added this to the v7.4.3 milestone Mar 25, 2019
@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Mar 25, 2019

I'm working on this. Is it correct that enum are block-scoped, it is not an error to declare a var/function/enum with the same name in the same block but it is an error to redeclare it using let/const?

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Mar 25, 2019

This is an error:

enum Foo { }
var Foo;

But this is not: (I'm assuming that this should throw)

{
    enum Foo { }
    var Foo;
}

🤔 cc @babel/typescript

@fenok

This comment has been minimized.

Copy link

commented Apr 27, 2019

Looks like the issue is still there. I managed to reproduce it in TypeScript-Babel-Starter (with actual dependencies) with that:

interface Test {}

export { Test }
SyntaxError: D:\TypeScript-Babel-Starter\src\index.ts: Exporting local "Test", which is not declared.
  1 | interface Test {}
  2 | 
> 3 | export { Test }
    |          ^

Original case works fine though :D

@fenok

This comment has been minimized.

Copy link

commented Apr 28, 2019

https://gist.github.com/fenok/f0ebbda0c19c6f7e68ffd34f80f46b56

Not sure why it says 7.4.0, @babel/parser in node_modules has version 7.4.4.

EDIT: Installed dependencies with npm instead of yarn, version in logs changed to 7.4.4, the issue is still there.

EDIT2: Speaking of repl, shouldn't it be plugin-transform-typescript? It removes interface, leaving export intact, which is exactly where the issue is coming from.

@lock lock bot added the outdated label Jul 28, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Jul 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants
You can’t perform that action at this time.