You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Resolve tsconfig.json extends path using node_modules resolution logic #18865
We excluded it during the initial implementation due to complexity, but left an error for it in so we could go back and add it later if we needed to. An issue here is that the module resolution strategy we use is determined by your compiler options... and an extends option can be specifying just what that module resolution scheme is, which is kind of a circular dependency - you must know your module resolution scheme to resolve an extends option, but your extends option can lead to where you specify some module resolution scheme!
Reacted by Aluan Haddad, Bob Myers, Nash Spence and Nicholas Jamieson
Reacted by Sindre Sorhus, Esteban Martini, Pelle Wessman, Boris Serdiuk, Felix Becker, Nate Ryall, Matt, Burkhard Reffeling, Olzhas Alexandrov, Dieter Geerts and 2 more
How about escaping the paradoxical loop by just letting Node.js resolve this as it normally would?
We do not always use node module resolution for your package (you have to specify in your configuration if you want node module resolution or a custom scheme - that's effectively what "moduleResolution": "classic" is), and it stands to reason that we'd use the same module resolution for your configuration as for your other files. Which leads to the issue that it becomes possible to not know what module resolution scheme to use to find your configuration until we have found your configuration, which is an issue.
And, if the external-package/tsconfig.json file also have a moduleResolution, then you throw an error like: 'moduleResolution' can't be overwritten because 'external-package/tsconfig' is already setting a value. And, if not, then you resolve trough the node resolution.
This right now is a "blocker" for me, because I have a "core" module with the settings that will be shared among all my modules, and because the path is relative to node_modules, and npm has now a flat tree, this breaks.
For now I'm resolving it by adding setting the value to ../external-package/tsconfig instead of ./node_modules/external-package/tsconfig, but this solution is dirty because in development I need to have the core module one level above the module I'm working on in order to make it work.
TSLint already have this resolved, you can make something like the example above without any issues.
I can't imagine why the node_modules being flat prevents you from resolving properly, Luke Shiru (Legacy) (@lukeshiru). I don't understand what you're doing there. Why do you resolve other than what my example shows?
tsconfig.json is not used after package is packaged, right? So my workaround should work.
How good of an idea would it be to use "extends": "./node_modules/typescript-config-foo/index.json" until this is possibly implemented?
Not a very good idea. In my mono-repo setup, the plan would be to have a config-like sub-repo, and it could end up getting put at a higher level, so you'd need to do ../node_modules/@myproject/config/tsconfig.json, essentially guessing where yarn would put things, which is exactly why I suggested some way to follow the built-in node module resolution algorithm.
Reacted by Lou Cyx, Frank Wallis, Mathis Wiehl, James Ravenscroft, Felix Becker, Burkhard Reffeling, Olzhas Alexandrov, Chad Ostrowski, Sang Dang and romdej
Luke Shiru (Legacy) (@lukeshiru) there is always a --moduleResolution, but it is often implied. --module commonjs implies --moduleResolution node, otherwise the language defaults to --moduleResolution classic.
If you then, have that children module used somewhere else (let's calle it other-children-module), that reference becomes invalid, because instead of having this:
Although by no means the only use case, the requirement might be simplest to understand by looking at the case where I want to install some config globally:
npm install --global cool-tsconfigs
Then use it by saying
"extends": "cool-tsconfigs/tsconfig.test.json"
Reacted by George Yong, Olzhas Alexandrov, iulo and Sergey Rotanev
I am confused by this reported "bug" because I have been using this feature extensively since it was implemented and it works exactly as expected. Perhaps something else is wrong in your case. You may need to provide more information or even a sample repo.
This definitely work properly for me at this point on 3.4 release in most scenarios.
I'll try to put together my reproduction case soon though. It's something like the following:
- ~/workspace/oss-core/
- ~/workspace/oss-core/tsconfig.json (extends `@vanilla/tsconfig/core.json`)
- ~/workspace/oss-core/plugins/proprietary-plugin (symlink to other directory).
- ~/workspace/proprietary-plugin
- ~/workspace/proprietary-plugin/tsconfig.json (extends `@vanilla/tsconfig/core.json`)
In this file structure I would expect the tsconfig extension to be capable of being discovered from when looked at through the symlinked file.
Instead oss-core/tsconfig.json works, but proprietary-plugin/tsconfig.json does not.
I think that the real file path is being resolved before evaluating the config file. I believe this is similar to the issue Luke Shiru (Legacy) (@lukeshiru) is describing, but slightly different.
In any case I can open a separate issue and try to make a sample repo for my issue.
Yet it fails as it's trying to extend from parent/node_modules/package/tsconfig.json instead of from parent/project/node_modules/package/tsconfig.json. Why is it looking for node_modules in the parent of the root instead of root itself?
Reacted by Russell Dempsey, Dieter Geerts, Abdullah Hilson, Cameron Flint, 정석호, Liam, Valentin Gurkov, Onur Fesci and Jimmy Multani
I also can confirm that this just doesn't work. Going through the code of that PR, I can only find out that the internal code is just over engineered and complicated for no apparent reason. Why is just doing require not an option here and just let node do his work?
We don't support any kind of .js based configuration. At all. You should just have a tsconfig.json in the package root, which, ofc, can't do anything dynamic.
Reacted by Moshe Brevda, Thomas, kdevan, Max, Dieter Geerts, Cristopher, Rodrigo Roa Rodríguez, Than Hutchins, Ashkan Pourghasem, Sabarni Das and 6 more
We don't support any kind of .js based configuration. At all. You should just have a tsconfig.json in the package root, which, ofc, can't do anything dynamic.
would such things be on the roadmap? As mono-repos are used more and more, it is useful to share config with the same includes following the globs that all projects inside the mono repo complies to and have dynamic things in it.
For example, we do this with our babel and nyc config, and that works like a charm.
Activity
aluanhaddad commentedon Oct 1, 2017
Seems like a good idea. If this feature is added, I think it would be important that it also work with
"paths".Maybe this would be a small
step toward Project References 😉
weswigham commentedon Oct 1, 2017
We excluded it during the initial implementation due to complexity, but left an error for it in so we could go back and add it later if we needed to. An issue here is that the module resolution strategy we use is determined by your compiler options... and an
extendsoption can be specifying just what that module resolution scheme is, which is kind of a circular dependency - you must know your module resolution scheme to resolve anextendsoption, but yourextendsoption can lead to where you specify some module resolution scheme!aluanhaddad commentedon Oct 1, 2017
Wesley Wigham (@weswigham) yeah that is paradoxical 😨. We find the source of truth only to learn from it that we were never meant to discover it...
mightyiam commentedon Oct 20, 2017
How about escaping the paradoxical loop by just letting Node.js resolve this as it normally would?
BTW, for reference and inspiration, all of these support resolving this to a package export:
mightyiam commentedon Oct 20, 2017
How good of an idea would it be to use
"extends": "./node_modules/typescript-config-foo/index.json"until this is possibly implemented?weswigham commentedon Oct 20, 2017
mightyjam that's a relative path, so it's fine.
We do not always use node module resolution for your package (you have to specify in your configuration if you want node module resolution or a custom scheme - that's effectively what
"moduleResolution": "classic"is), and it stands to reason that we'd use the same module resolution for your configuration as for your other files. Which leads to the issue that it becomes possible to not know what module resolution scheme to use to find your configuration until we have found your configuration, which is an issue.loucyx commentedon Oct 25, 2017
The solution can be something like setting the
moduleResolutionin the "children":{ "extends": "external-package/tsconfig", "compilerOptions": { "moduleResolution": "node" } }And, if the
external-package/tsconfig.jsonfile also have amoduleResolution, then you throw an error like:'moduleResolution' can't be overwritten because 'external-package/tsconfig' is already setting a value. And, if not, then you resolve trough the node resolution.This right now is a "blocker" for me, because I have a "core" module with the settings that will be shared among all my modules, and because the path is relative to node_modules, and npm has now a flat tree, this breaks.
For now I'm resolving it by adding setting the value to
../external-package/tsconfiginstead of./node_modules/external-package/tsconfig, but this solution is dirty because in development I need to have the core module one level above the module I'm working on in order to make it work.TSLint already have this resolved, you can make something like the example above without any issues.
mightyiam commentedon Oct 26, 2017
Yup. I'm the same use case as Luke Shiru (Legacy) (@lukeshiru).
I can't imagine why the node_modules being flat prevents you from resolving properly, Luke Shiru (Legacy) (@lukeshiru). I don't understand what you're doing there. Why do you resolve other than what my example shows?
tsconfig.json is not used after package is packaged, right? So my workaround should work.
rtm commentedon Oct 26, 2017
Not a very good idea. In my mono-repo setup, the plan would be to have a config-like sub-repo, and it could end up getting put at a higher level, so you'd need to do
../node_modules/@myproject/config/tsconfig.json, essentially guessing whereyarnwould put things, which is exactly why I suggested some way to follow the built-in node module resolution algorithm.aluanhaddad commentedon Oct 26, 2017
Luke Shiru (Legacy) (@lukeshiru) there is always a
--moduleResolution, but it is often implied.--module commonjsimplies--moduleResolution node, otherwise the language defaults to--moduleResolution classic.loucyx commentedon Oct 26, 2017
Shahar "Dawn" Or (@mightyiam) the problem is mentioned by Bob Myers (@rtm). Let's say you have you children module using the parent's module config like this:
children-module/tsconfig
{ "extends": "./node_modules/parent-module/tsconfig" }If you then, have that children module used somewhere else (let's calle it
other-children-module), that reference becomes invalid, because instead of having this:Now you have this:
The flat dependency tree makes children and parent at the same level. So for that to work you need children-module to have the config changed to:
{ "extends": "../parent-module/tsconfig" }The ideal scenario should be to solve it like TSLint does, by setting it like this:
{ "extends": "parent-module/tsconfig" }And letting node resolve it.
loucyx commentedon Oct 26, 2017
Aluan Haddad (@aluanhaddad) that still doesn't solve the issue. See my comment above for clarification.
rtm commentedon Oct 26, 2017
Although by no means the only use case, the requirement might be simplest to understand by looking at the case where I want to install some config globally:
Then use it by saying
15 remaining items
loucyx commentedon Jan 21, 2019
Hey Wesley Wigham (@weswigham)! I think that PR didn't fixed this issue. I have a repo with settings and I'm trying to extend them like this:
And instead of looking for it in the
node_modulesdirectory, it looks for it in the cwd, which is not the expected behavior. If I use this instead:It will break because that only works in this scenario:
But then if I use
children-moduleit breaks in this scenario:Because is not anymore in
child-module/node_modules, instead it is inchildren-module/... You are forgetting about plain structures...charrondev commentedon Feb 28, 2019
Wesley Wigham (@weswigham) Any chance this could be re-opened. As Luke Shiru (Legacy) (@lukeshiru) points out this hasn't been properly implemented. The current implementation is not in line with the described Module resolution
nodein the typescript documentation.mightyiam commentedon Jun 10, 2019
Luke Shiru (Legacy) (@lukeshiru), Adam Charron (@charrondev), please allow me to suggest that opening a new issue might help. You know how no-one likes reopening closed issues.
rtm commentedon Jun 10, 2019
I am confused by this reported "bug" because I have been using this feature extensively since it was implemented and it works exactly as expected. Perhaps something else is wrong in your case. You may need to provide more information or even a sample repo.
charrondev commentedon Jun 10, 2019
This definitely work properly for me at this point on
3.4release in most scenarios.I'll try to put together my reproduction case soon though. It's something like the following:
In this file structure I would expect the tsconfig extension to be capable of being discovered from when looked at through the symlinked file.
Instead
oss-core/tsconfig.jsonworks, butproprietary-plugin/tsconfig.jsondoes not.I think that the real file path is being resolved before evaluating the config file. I believe this is similar to the issue Luke Shiru (Legacy) (@lukeshiru) is describing, but slightly different.
In any case I can open a separate issue and try to make a sample repo for my issue.
TidyIQ commentedon Jun 19, 2019
I'm not sure how people are saying this works... My project structure is like so:
And contents of `parent/project/tsconfig.json is:
Yet it fails as it's trying to extend from
parent/node_modules/package/tsconfig.jsoninstead of fromparent/project/node_modules/package/tsconfig.json. Why is it looking for node_modules in the parent of the root instead of root itself?dietergeerts commentedon Oct 17, 2019
I also can confirm that this just doesn't work. Going through the code of that PR, I can only find out that the internal code is just over engineered and complicated for no apparent reason. Why is just doing
requirenot an option here and just let node do his work?dietergeerts commentedon Oct 17, 2019
I also want to note that it doesn't work by just doing:
Why am I trying this? Because I want to have an
.jsfile where I can dynamically build the config depending on the project extending it.weswigham commentedon Oct 17, 2019
We don't support any kind of .js based configuration. At all. You should just have a tsconfig.json in the package root, which, ofc, can't do anything dynamic.
dietergeerts commentedon Oct 17, 2019
would such things be on the roadmap? As mono-repos are used more and more, it is useful to share config with the same includes following the globs that all projects inside the mono repo complies to and have dynamic things in it.
For example, we do this with our babel and nyc config, and that works like a charm.
weswigham commentedon Oct 17, 2019
Go open an issue - #30400 kinda tracked it but was closed by the author.
refactor: use yarn workspaces for easier install
refactor: use yarn workspaces for easier install
refactor: use yarn workspaces for easier install
LinqLover commentedon May 4, 2021
I think we should have the same option for the
includefield as well.