-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
Acknowledgement
- I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.
Comment
This is about the contents of https://www.typescriptlang.org/tsconfig/#extends
This issue doesn't fit a template, but is also not about the website, rather about what behavior to expect from TypeScript tooling and configs. Specifically the field's syntax and how it affects evaluation, which together the title phrases as resolution.
@RyanCavanaugh mentioned such issues can be opened directly in the TypeScript repo (see comment).
I no longer think that updates to extends docs wouldn't benefit the reader (as stated once in a comment)
I think mentioning Node.js style resolution for the config extends field, without clearly explaining how specifiers are resolved leads to misunderstandings of what to expect when using specifiers, starting with recognizing the diff between a path and a specifier.
Reasons being:
- @RyanCavanaugh already mentioned
extendsdocs to be outdated in another comment - Document that compiler.extends can be an array #62915 mentions further updates to
extends - other tools are considering updates to their implementation to adapt to new features of engines that involve support for
extendsand would probably benefit from up to date documentation (see esbuild issue 4360) - previous attempts to align
extendsresolution in tools building on top of TypeScript tackled resolution according to Node.js, rather than using TS config resolution (the latter being undocumented or outdated and potentially misleading), as can be seen in this VSC pull request being an attempt to close a related issue, in which in turn it is mentioned at least once that resolution is not the same and that the docs are unclear or outdated in this regard; also mentioning some of the differences and that resolution should follow compiler behaviour, not some engine unrelated to compiler configs.
I've copied the list of differences I am aware of from one of the linked issues down here below, since they are directly relevant to this issue:
- ts normalizes paths differently than node does (e.g. ts normalizes
\\path separators [even in specifiers], node doesn't). - node supports some protocols that tsc doesn't support for
extends(e.g. in node you can importnode:,data:andfile://). - Node has file extension restrictions, tsconfig has not.
- In node only specifiers starting with a dot indicate relative imports, while in tsconfig everything is relative unless it starts with at (@) or hash (#) or syntax indicating a root (I'm only aware of path separators, but maybe there's logic to handle drive letters?).
- this also means you cant extend configs of unscoped packages (e.g.
import "unscoped-bare"is node, but would be"extends": "relative"in tsconfig).
Apart from those syntactic differences, it would be worth noting that tsc is largely unaware of packages (support of package/module specifier syntax suggests otherwise).
This has noteworthy implications for monorepos, project boundaries and relative paths in config files. E.g. one could test and answer the following question, but it would be nice if it were documented:
What happens if I extend the config of another package from within a monorepo which has its own files or includes, without explicitly overriding files or includes? Will the current (implicit) defaults override the inherited or do I have to be explicit to override inherited entries? It must be the latter, otherwise it would never inherit. For monorepos this means one has to be careful not to include files from other packages (or the opposite, based on what you think would be intuitive), because resolved paths don't resolve to a node_modules subpath. The consequence would be inclusion of other package sources, as well as rendering skipLibCheck ineffective.
Also not clear from the docs on extends: Does files or includes override all inherited entries, or only the corresponding field? Following the links for docs on those fields it is not clear how those interact or interfere, neither per config file, nor when it comes to inheritance. Same for exclude. Does it affect include on a per file basis, or is it inherited as a field that will affect inheriting includes? A naive guess would be, fields are inherited independently, but that info is missing.
Search phrase I used to avoid opening a duplicate: "update docs tsconfig extends"
- this is similar to TSConfig
extendsdoes not resolve Node.js style specifiers #62753; the difference being, the other claimed buggy behavior, while this is about the lack of documentation or specification - previous issues about outdated docs led to positive results; example of a successful update: FAQ on module specifier rewriting is outdated #62705