[EPIC] Full TS-style resolution hooks · Issue #1514 · TypeStrong/ts-node (original) (raw)

Note: if you're here following a link from our docs about experimentalResolver, you know that our docs for this feature are currently quite limited. Feel free to experiment and ask questions in Discussions or on Discord. This epic tracks the development work to finish all the resolver features and eventually promote them out of experimental status.

Current status

Describes state of our main branch, may not be published to npm yet


Motivation

In TS, you import the emitted output path, and the compiler resolves this to the input source. They might have different extensions or be in different directories.

In ts-node, we should do the same.

Creating an epic to link together all the related tickets and tasks to make this happen.


How this works in TS

It's been a while since I read the TS code.

I believe that TS creates a mapping from all source files to their emit paths. It can do this because it starts with a glob of all source files, then computes the output path for each in a loop.

Aside: Does this work with files not included in a files array? Does it trigger inclusion of those files in compilation? If yes, that would violate my understanding above.

How it'll work in ts-node

ts-node must do the opposite of TS: we start from a runtime require() or import request, then work backwards to a source TS file. We don't know if such a source file exists; we might be importing a non-compiled .js file.

Mappings to keep in mind:

Supported extensions are affected by:

Questions

"Resolve to source path" vs "pretend emit exists on disk"

When resolving from ./dist/foo.js to ./src/foo.ts we have 2x options:

ts-node today does (B) but does not do most of the advanced resolution we'd be implementing in this epic.

(B) is closer to deno and probably what people want. __filename and import.meta.url will refer to the actual TS file being executed. This is technically slightly different than pre-compilation execution. However, my gut tells me users will be happier with an intuitive __filename and won't mind the slight difference with pre-compilation.

Note: resolve hook is equivalent to _resolveFilename, load hook is equivalent to compile() hook

ignore with resolver

If src/index.ts is ignored and dist/index.js resolves to src/index.ts, should the resolver do that mapping?