Skip to content

TypeScript, Ts-Node, isExternalLibraryImport #1021

Description

@arcanis

I'm curious to hear your thoughts regarding a particular interaction. Picture the following monorepo:

/app/tsconfig.json
/app/packages/foo/index.ts -> import 'bar';
/app/packages/bar/index.ts

Now this is what happens:

  • ts-node doesn't implement the realPath function in serviceHost (here)

  • As a result, TS will resolve the import 'bar' into /app/node_modules/bar/index.ts - it won't transform it into /app/packages/bar/index.ts.

  • Then the transformed file is passed to Node, which resolves the require('bar') again, but this time applies a realpath on it. It goes into ts-node, which transpiles it (since from TS' perspective, it has never seen this path from its life). So far so good.

But now here's the trick: what happens if we fix the initial bug, and add a realpath implementation to serviceHost? Things break, because:

  • TS will resolve the import 'bar' into /app/packages/bar/index.ts, but it will also set the isExternalLibraryImport flag (because it's hardcoded to do so).

  • As a result, it will not emit files for /app/packages/bar/index.ts. Then Node will run the require('bar') again, but since this time /app/packages/bar/index.ts was seen by TS (but wasn't transpiled), ts-node crashes with:

TypeError: Unable to require file: packages/bar/index.ts
This is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or other executable extension with loader attached before `ts-node` available.

So what to do? I've tried fixing TS to set isExternalLibraryImport to false (so that it gets transpiled), but that has adverse effect on tsc - which then builds dependent workspaces on top of the current one (precisely because TS starts emitting files for them).

Now you might wonder: "what if we just don't fix the realpath bug?". It's a valid approach, but it's only one of the two ways to trigger the bug. If you use PnP (which doesn't use symlinks anymore for workspaces), you get the same result (since all paths are now realpaths). As a result, using together ts-node w/ TS and workspaces doesn't work.

I guess my suggestion would be to set the realpath property (for correctness), and to avoid relying on TS always returning all the files unless their transpilation has been explicitly requested.

More details and reproduction: microsoft/TypeScript#37270

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions