Skip to content

transpileModule does not elide type only "import equals" #49450

Closed
@wnayes

Description

@wnayes

Bug Report

I've encountered a pattern where transpileModule emits unsafe code at runtime, and isolatedModules does not report errors to help catch this case.

Consider the following:

import IInterface = My.Application.Interfaces.IInterface;
export type { IInterface };

Under a "normal" full compile, TypeScript will recognize that IInterface only used as a type, and will essentially emit nothing for either of these lines.

export {};

But when this same snippet is ran through transpileModule, the "import equals" declaration is preserved as a variable.

var IInterface = My.Application.Interfaces.IInterface;
export {};

It isn't safe to assume that My.Application.Interfaces is going to be available at runtime, and this difference could lead to runtime errors.

🔎 Search Terms

isolatedModules import equals namespace type only

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about transpileModule.

⏯ Playground Link

Playground link demonstrating the desired output:
https://www.typescriptlang.org/play?isolatedModules=true&ssl=4&ssc=28&pln=3&pc=1#code/PTAEAEEsGcHsBsCGAXApgEwLK3QV3qtAFyjIBOuqAUFZALYAOsZyoAkmwHZpkBmiAY1SgAvKEwBPAHQBBBg3iQBKSLE5SuPfkOgbNqPoNQBuKqgAeTFqQkNhAb3b7DQ0AF9TVEKAAiqAUhkGKBwdKgA7gAWBsKo8NCoRFTo-oHCAObwsABGiPCg9lSgxaCciGHQDEbi0nIKSipqGtwG2oQFRSVdkC0uwhy9bQVuncUjbkA

Code Sandbox showing the problematic transpileModule behavior:
https://codesandbox.io/s/cocky-mcclintock-9iuqd9?file=/src/index.js

💻 Code

This is essentially what the Code Sandbox is doing:

const result = ts.transpileModule(`
import IInterface = My.Application.Interfaces.IInterface;
export type { IInterface };
`,
  {
    compilerOptions: {
      module: ts.ModuleKind.ESNext
    }
  }
);

🙁 Actual behavior

var IInterface = My.Application.Interfaces.IInterface;
export {};

🙂 Expected behavior

export {};

Suggested Fix

  • Correctly elide the import equals declaration, just like regular import statements.
  • Or protect developers against this runtime risk through an error when isolatedModules is enabled. (However, I don't know of a great replacement for this syntax if this was the direction taken.)

For reference, #45579 was recently fixed, where isolatedModules now reports an error for code like this:

export import JSX = JSXInternal;

It seems to me like developers are going to quickly fix these cases by doing something like this:

import JSX = JSXInternal;
export type { JSX };

And that is the exact pattern I am reporting in this issue.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions