microsoft/TypeScript

TypeScript transformers don't bind imports added during a transformation

itsdouges opened this issue · 2 comments

TypeScript Version: 3.7.x-dev.201xxxxx

Search Terms:

Code

https://github.com/atlassian-labs/compiled-css-in-js

Expected behavior:

  • Usage of imports get renamed when targetting CJS modules
  • Imports do not get removed when they are used

Actual behavior:

Playground Link:

Related Issues:

I have no idea how the auto react import will work without this being fixed.

There are some features of the compiler you can employ to produce the same generated name for the react import. The name react_1 is a special GeneratedIdentifier node and isn't value isn't known until after transforms are run and emit occurs. You can create a GeneratedIdentifier for a specific node using getGeneratedNameForNode, which will always generate the same name for the same node. The CommonJS transformer uses that behavior for the module name for a default import:

// import d from "mod";
// import { x, y } from "mod";
// import d, { x, y } from "mod";
// import d, * as n from "mod";
variables.push(
factory.createVariableDeclaration(
factory.getGeneratedNameForNode(node),
/*exclamationToken*/ undefined,
/*type*/ undefined,
getHelperExpressionForImport(node, createRequireCall(node))
)
);

You can use the same behavior to get the generated name for the react import node in your own code, given the current transformation's input SourceFile:

  1. Get the original parse-tree SourceFile using getParseTreeNode(file). This will give you the SourceFile as originally parsed before any transformations have been applied.
  2. Search statements of the original SourceFile to find an ImportDeclaration for "react".
  3. Use getGeneratedNameForNode(node) on the ImportDeclaration.

This will give you a GeneratedIdentifier corresponding to the ImportDeclaration that will produce the same identifier value that the CommonJS transform uses.

To clarify, this isn't a bug in the compiler, but rather is due to the nature of how the transforms work. Binding and type-checking occur before any transformations are evaluated and transformed nodes are never re-bound.