alangpierce/sucrase

Typescript import-equals is transpiled incorrectly

janmeier opened this issue · 4 comments

Sample code:

import { Foo } from 'foo'
import Bar = Foo

console.log(Foo)
console.log(Bar)

tsc output playground

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var foo_1 = require("foo");
var Bar = foo_1.Foo;
console.log(foo_1.Foo);
console.log(Bar);

sucrase output (using sucrase@3.27.0)

"use strict";var _foo = require('foo');

const Bar = Foo

console.log(_foo.Foo)
console.log(Bar)

Context

This is in ts code generated by graphql-codegen, so I cannot easily change it. I found a similar esbuild issue, evanw/esbuild#1283

I hope this is within the scope of sucrase 🤞

Hi @janmeier , thanks for the report! Yes, this is in-scope for Sucrase to handle. I'll try coming up with a fix when I get a chance. I think it should be pretty easy, the code to the right of the = just needs to fall back to the root transformer so it applies any other relevant code transformations (usually unnecessary inside an import statement).

I took a closer look and it's harder than I expected, but should still be doable. I made a related fix back in #441 , and it turns out that this import = syntax is the one case in TypeScript where you potentially need to traverse an arbitrary-length chain of import statements to see whether an import should be kept or removed.

If I just change Foo to be a regular variable access, then it would start incorrectly preserving the import in cases like this:

import {Foo} from 'type-only-file-that-doesnt-exist-at-runtime';
import Bar = Foo;
const b: Bar = {};

The ideal fix is to just implement TypeScript's behavior, though there may be a simpler fix for just this reported case if I make Foo a special identifier type that gets transformed by the imports transform but doesn't count as a reference for import elision reasons (which should be strictly an improvement over the current behavior). I'll explore the options a little more to see what makes the most sense here.

Thanks, I appreciate you looking into this!

Luckily this only occurs if you import a type in codegen and then rename the type. So in our case we can simply change how types are exported for gql codegen to work around the issue

Nice to know