Skip to content

Module resolution - four issues (specific and simple to general) #31466

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lll000111 opened this issue May 19, 2019 · 3 comments
Open

Module resolution - four issues (specific and simple to general) #31466

lll000111 opened this issue May 19, 2019 · 3 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@lll000111
Copy link

lll000111 commented May 19, 2019

I know there have been plenty of questions around module resolution, I read some of them (SO and here). I still have these issues: The most general one last, the most specific one first.

1 Fix documentation

From page https://www.typescriptlang.org/docs/handbook/module-resolution.html

Classic

This used to be TypeScript’s default resolution strategy. Nowadays, this strategy is mainly present for backward compatibility.

But "Classic" still is the default, no?

This sounds like it should not be the default.

2 Don't ascend above project directory

(At least not by default, or provide an option to prevent it.)

Why is TS allowed, by default, to ascend up out of the project directory?

I have a folder Projects/ with various projects, some included by others, but via packages and not directly from those directories but they have the same name locally. What happens is that when I run tsc in one of those projects it ends up including definitions from another project instead of from node_modules/, which makes no sense to me. I mean I get it if that was an optional behavior, but by default going into folders that don't belong to the project?

How can I prevent tsc from looking for anything outside the current project's directory?

3 Include node_modules in module resolution

What I mean is that it should always be used, or at least make it configurable but not as it is now where it depends on module resolution "node". The use of node_modules is not node.js specific at this time.

I'm also confused because TS does find things <PROJECT_ROOT>/node_modules, it only finds @types imports. I bundle .d.ts files in my own library, which since it's internal and private has no way to get its .d.ts published via DefintelyTyped. When I import from "myLib/lib/someFile", for which a .js and a .d.ts and a .d.ts.map file exists, it only finds it in "node" module resolution mode.

It may as well include that folder in its search even in "Classic" mode, that IMHO makes more sense than the search outside the project directory.

4 Module resolution depends on build target

First I checked if this still applies, and it does.

In reference to:

  1. I don't see that mentioned in the docs (page linked above)
  2. I don't understand the purpose

At least for me, the build and development are orthogonal. I build for browser, react-native, node.js and experimentally even for two embedded platforms (Moddable, low.js) and I don't see why my code structure used for development should depend on the build target! After transpiling (here using Babel, but that would be the same if we used TS for that) module resolution on the various platforms is vastly different. From webpack-packages to a "flat" module namespace (Moddable, many platforms use their own very different module handling. Whether Webpack or Moddable find a module has nothing whatsoever to do with TypeScript used while writing the code and how it type-checks and finds modules.

IMHO development time module resolution should not depend on the build target.

My own build target is "esnext" (I also have "noEmit": true because I only use TS at development time, if there is any transpilation it is done by Babel, usually that's just removing the type annotations and maybe a — flexible — module system target), but even node supports ES2015 modules these days, so I don't think there is the direct connection between "commonjs" and "node_modules" any more, if ever there was.

Especially since the support of the Babel option the distinction that already and always existed between development with type checks (when the type checker needs to be able to find a) included modules, but b) also just type info like .d.ts files which have no runtime equivalent and there location surely should not depend on what the build target is), transpiling and packaging, and running the code, probably deserves another look to remove unnecessary cross-concern bindings like module resolution (used for type checking) depending on transpilation (which does not even need to know about where to find modules since it is in between type checking and runtime).

On a more general note, I think TS has too tight a coupling because those concerns, which despite all efforts I can see even here in the "Issues" in reaction to feature requests where anything that would make TS different from JS is routinely rejected, leads to a lot of confusion esp. among new(er) developers (to the ecosystem, not necessarily by age) that TS is a different language. Especially since Babel workflows are officially supported too now the more clear separation of development time (type checking) and transpilation might be beneficial. It's not even a code change, maybe a few tsconfig layout changes at most.

 

 

As an aside, there is even more of a disconnect between development and runtime. I, for example, use TSypeScript only for type checking. It's a setup I could also run with Flow, same for anyone that uses Babel for transpilation (many people don't seem to know, all the Babel-TS plugin does is remove the types, because then TypeScript code is just "ESnext" (if one doesn't use namespaces, enums, import=/export=).

That means I use tsc only from the IDE as language service and for type checks. It (tsc) only needs to understand the layout of the code during development. It does not need to concern itself with either transpilation or where modules might be found during runtime — especially the latter, in the days of Webpack & Co., is something tsc does not need to know. So finding files and types (.d.ts) during development should be separate from finding code modules during runtime, and TS should focus on the former (the latter is the domain of various build systems anyway, which have their very own ideas).

That means that, for example, I can use TS-only features like namespaces for my types (inside a .d.ts file) even if I would not or can't use it in my code. In my particular case it helps with type checks (declaration merging between a private lib an apps using it, just my particular private case and example).

So in my — I would claim not unusual — setup, 1) type checking (by tsc), 2) transpiling (by Babel), 3) packaging (Webpack, Moddable compiler, React Native, and others) and then 4) the actual runtime all are disconnected. This is in line with the architecture of TS I think, the merging of concerns is, I think, a product of user-facing components. I don't think tying those components together, for example by binding module resolution (used during development for type checks) on a build target (used only when actually building, and even that does not necessarily need to be done with tsc since there is the Babel option) is not good.

@lll000111 lll000111 changed the title Module resolution doc is ambiguous Module resolution doc is ambiguous (and module. res.) May 19, 2019
@lll000111 lll000111 changed the title Module resolution doc is ambiguous (and module. res.) Module resolution - four issues (specific and simple to general) May 19, 2019
@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Jun 12, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.6.0 milestone Jun 12, 2019
@sheetalkamat
Copy link
Member

@RyanCavanaugh @DanielRosenwasser Whats the action needed here? I am not sure what we can do here?

@RyanCavanaugh
Copy link
Member

@lll000111 there's a lot to unpack here and this seems like a mix of reactional feedback (something didn't work the way you expected it to - this is fair to note, but generally unactionable on our side), possible bugs (the docs should be accurate if they're not), design change proposals (e.g. decoupling target/module resolution), and feature proposals.

It'd be useful on our end if you could be more clear about what you expect to be different, and ideally in separate issues.

@RyanCavanaugh RyanCavanaugh removed this from the TypeScript 3.6.1 milestone Jul 31, 2019
@RyanCavanaugh RyanCavanaugh added Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. and removed Needs Investigation This issue needs a team member to investigate its status. labels Jul 31, 2019
@RyanCavanaugh RyanCavanaugh removed their assignment Jul 31, 2019
@RyanCavanaugh RyanCavanaugh added the Suggestion An idea for TypeScript label Jul 31, 2019
@DanielRosenwasser
Copy link
Member

But "Classic" still is the default, no?

It is unless you use --moduleResolution node. It is correct that there's a doc update needed, but we're working on new docs.

There's also an open issue about this: #11434

Don't ascend above project directory

You can control this with --rootDir, and you'll get an error if you resolve outside of the rootDir.

What I mean is that it should always be used, or at least make it configurable but not as it is now where it depends on module resolution "node". The use of node_modules is not node.js specific at this time.

I'm also confused because TS does find things <PROJECT_ROOT>/node_modules, it only finds @types imports.

This is because of the typeRoots option walking up the directory chain for node_modules/@types directories. You can explicitly include node_modules as well as node_modules/@types for your typeRoots. See more here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants