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.
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
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.
Bug Report
I've encountered a pattern where
transpileModuleemits unsafe code at runtime, andisolatedModulesdoes not report errors to help catch this case.Consider the following:
Under a "normal" full compile, TypeScript will recognize that
IInterfaceonly used as a type, and will essentially emit nothing for either of these lines.But when this same snippet is ran through
transpileModule, the "import equals" declaration is preserved as a variable.It isn't safe to assume that
My.Application.Interfacesis 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
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
transpileModulebehavior:https://codesandbox.io/s/cocky-mcclintock-9iuqd9?file=/src/index.js
💻 Code
This is essentially what the Code Sandbox is doing:
🙁 Actual behavior
🙂 Expected behavior
Suggested Fix
isolatedModulesis 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
isolatedModulesnow reports an error for code like this:It seems to me like developers are going to quickly fix these cases by doing something like this:
And that is the exact pattern I am reporting in this issue.