Repository navigation
Feature request: allow user to merge extended arrays in tsconfig files #20110
Description
Activity
Personally, I'd sooner like to see a
tsconfig.jsortsconfig.tsaffordance (similar to a webpack config) to generally leverage JS syntax for complex configuration merging rather than introduce special-snowflake "syntax" into a json file with complex layering and execution semantics. There's already a thing that exists to describe these kinds of procedural transforms, and it's called "code".Reacted by Bob Myers, Jules Sam. Randolph, Lorenzo Dalla Vecchia, Adam, Hayden, Kenji Imamula, Jean-Baptiste Musso, Gavin H, Donald Pipowitch, Seb Insua and 151 moreReacted by Vladislav Spivak, Jonathan Holford and ChurroCReacted by Wesley Wigham, Hayden, Nate Ryall, Iliyan Iliev and Son SuminReacted by Aluan Haddad, Hayden, Steve, Mehrad Rafigh, Nate Ryall, Son Sumin, ChurroC, Austin Biggs and ClassifiedsReacted by Daniel Rosenwasser, 弹铁蛋, Aamir Jawaid, ChurroC, Chenfeng Bao and ClassifiedsReacted by Son Sumin, Dibo, David Barker, Fahim Ali Zain, Austin Biggs, Classifieds and lex00- addedIn DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript
on Nov 17, 2017 Personally, I'd sooner like to see a tsconfig.js or tsconfig.ts affordance (similar to a webpack config) to generally leverage JS syntax for complex configuration merging rather than introduce special-snowflake "syntax" into a json file with complex layering and execution semantics. There's already a thing that exists to describe these kinds of procedural transforms, and it's called "code".
Noooooooooooooooo.
Reacted by Ryan Cavanaugh, Wesley Wigham, Max, Vladislav Spivak, Dan The Dev, diego, Adam, Aamir Jawaid, Ahmed, Roman Astashevich and 2 moreReacted by Anıl Anar, Ersin Akinci, Steve, Piotr Styczyński, Aditya Thakral, Jakub Jirutka, Fernando H-T Goldáraz, Aki, Amir, Nate Ryall and 49 moreReacted by Aluan Haddad, Vincent, Erik Medina, Fahim Ali Zain and KasopejReacted by Aluan HaddadWe did talk about the OP when we first put in the configuration inheritance in place, and had a proposal of
extendsandoverwritesto be two different behaviors for cases like these.. but in the end we chose to avoid complexity and just go withextendsmeaningoverwrite. i think in hindsight that was a good discussion, and most users did not have the need for additional complexity. i would say for this request as well, the additional complexity (both in supporting the feature, and for users tsconfig.json files) is not worth the value you get out of it.Reacted by Jules Sam. RandolphReacted by Pavlo Valor, Son Sumin, Camille TJHOA, Ehsan Yaqubi, Harry Yaprakov, Yiin, jimbali, Sanaruca, Dibo, Samy Rahmani and 13 more"Do not over-complicate the implementation with abstractions where a little copying will suffice" - Unattributed programming koan
Reacted by Aluan Haddad, Josh Sommer, Andrew Smith, David Wickes, Son Sumin, Steffen Glückselig, Johannes Lindgren and floratminReacted by Mohamed Hegazy, Josh Sommer, Vlad Trishch, David Wickes, Son Sumin, Son Nguyen, Austin Biggs and lex00I understand the points you all made - especially the programming koan -, and I am only a novice. However you might be interested in the use-case : a project with many npm libraries acting as program modules, orchestrated with yarn workspaces and lerna. In such a situation, I find configuration reusability extended to the feature I proposed very convenient and clean.
Reacted by Steffen Glückselig, quirin-buechner-mdctec, Gonçalo Tavares, Rafa Horo, Andrei and ClassifiedsReacted by Juliano Brasil, Classifieds and penguintreeAs a side note, I find in some of your comments sarcasm I was absolutely not expecting from typescript repo maintainers. You don't need to scorn at people to make your point.
Reacted by Stav Noy and penguintreeSorry if I came off a bit sarcastic (I suppose quotes around things in text imply sarcastic airquotes). I probably should have used italics to imply emphasis and emphaticness rather than quotes in my first comment. I do understand the desire for reusable configuration, I just want the conversation and discussion on the issue to remain a bit light-hearted (and attempted to set such a tone) as once you start talking about code as configuration like I was, in my experience people start having very strong opinions (both for and against). I mean no slight to either your suggestion or you personally.
Reacted by matt morris, Jonathan Holford, Ben Cawrse, Gonçalo Tavares, Shannon Scott Schupbach, Stav Noy and Muthu KumarWesley Wigham (@weswigham) I greatly appreciate this clarification :-) But just to understand your viewpoint, would you really rather have a tsconfig.js ? Or, at the same time you consider code more appropriate and a javascript config file off-putting as too webpackish (the team reaction to your post is confusing) ?
I, personally, would prefer a code file. Mohamed Hegazy (@mhegazy) disagrees. :)
As I said, strong opinions.Wesley Wigham (@weswigham) OK, then I'm totally with you on this. Either through extended syntax or "codable" config file, I would love the feature.
Code file is not statically alayzable. We have a whole set of tools that rely on this config file to drive user experiences. Code file is a non starter.
Reacted by snarbiesAs I noted earlier, we have discussed such configuration inheritance use cases when we were implementing the feature; as a matter of fact Wesley Wigham (@weswigham) when he first propsed it had an extends and overrides, he also had multiple inheritance support. Back then we chose to not complicate the feature and ended up pulling the plug on these two proposals.
After having this in use for a few years now, I do not see that as a bad choice, and I do not think there are new use cases that are blocked by that decision.
And yes, it would be nice if you can configure every possible inheritance model you can think of; but features come with a cost, both for the compiler and toolset maintainers and for new users. There is always a trade of.
Mohamed Hegazy (@mhegazy) Thank you for both your posts which were very insightful. This is only speculation, but perhaps the shift towards monorepos (here is typescript workspaces plugin) will make the need for high config reusability more widespread.
Reacted by Steffen Glückselig25 remaining items
Support
<inherit>as object-key and array-value, which we use whenever we don't want to merge each and everything.I'd be +1 on
<inherit>. Pros:- It's backwards compatible.
- It's explicit.
- It's easy to understand.
- It allows for not merging (by omitting it) if that's not what you want.
Reacted by Top Master, Mauricio, Audun Meek Olsen, Ulrich, Mingcheng Li, Vinci, Kohei Matsubara, Mekhi, vs-johnny-huang, ChiefORZ and 7 more+1 on having the option to merge.
Reacted by Gonçalo Tavares, Tobias Goulden Schultz and floratminHere to vote for the
<inherit>solution.If code is not an option, at least provide a way to inherit to avoid the redundent copying right?
Plus, if I want to overwrite or exclude some of it, just use the same key with an empty value:
{ "extends": "../tsconfig.json", "compilerOptions": { "baseUrl": "./", "paths": { // The value should be an empty-string for now, // but in future, maybe also support RegExp pattern as value, which further filters what we inherit ;-) "<inherit>": "", "@shortcut/*": ["src/app/my-module/*"], // duplicated key to overwrite "@here's-to-overwrite/*": ["src/path/*"], // empty value to exclude "@here's-to-exclude/*": "" } } }Reacted by Gonçalo Tavares, Subir, Tobias Goulden Schultz and SuryaBecause "
<inherit>" is not just for "paths", the mentioned empty-string ornullmay already be used for something else.Hence, I prefer the RegExp filter idea that was mentioned:
"... support RegExp pattern as value, which further filters what we inherit ..."
Using that, we could simply use the "
(?!...)" negative look-ahead pattern,
to tellTSCthat it should inherit any object-key, except the keys listed, like:{ "<inherit>": "/(?!key-to-exclude-here|some-other-key-to-exclude)/gi" }Note that even tools that allow code use Regular-Expressions in such cases, for example see:
https://stackoverflow.com/a/55803188/8740349Reacted by František Žiačikwould love to see the implemented. I am unable to use both tsconfig.base paths (nx monorepo libs) and tsconfig.local paths (relative path cleanup).. it's one or the other
Reacted by Vitalii Samofal, ChiefORZ, Semaphor, Karl Podger, jesusvallez, Sanaruca, Anton Vlasov, Samy Rahmani, Timur Mishagin, Ankur Bargotra and 14 moreVery surprised to find that this is not possible given the maturity of TS and the prevalence of monorepos. At the moment Im having to replicate "../../../../pathnames" to common resources throughout my project tsconfigs when they are already defined in a common tsconfig root.
Are there any alternative configurations to using extends directive? e.g. project references? Im reading up on it but dont know enough about it yet.
Reacted by Marc SiegelWe use a pnpm monorepo with a handful of internal packages. I wrote a script which walks all the project references in a top-level tsconfig.json file, gets their dependencies from the package.json, and updates
pathandreferencesin each tsconfig.json to point at the required packages.https://github.com/proxy/gist.github.com/laverdet/a192df6ca10458e6fd2c2b32330c5923
Reacted by Oleksii Lukin and Kristian GerardssonExtending from base configs is pretty painful due to this limitation.
Would appreciate some movement on this by the TS team.Reacted by João Ferreira, Jørgen M. Skogås, Son Sumin, incompletude, Dan Cork, Daniel Newton, Ayhan APAYDIN, christopher1986, James Tu, Adam Drda and 20 moreAny progress on this issue ?
Reacted by João Ferreira, Derrick Hammer, Gipo, Artyom, Vinci, Markus Ahrweiler @Amcon Software GmbH, floratmin, Marc Siegel and snarbles2Having the same issue as the others.
In an nx monorepo, i'm forced to choose between having root paths or local paths.
On a side note, from day one it made me scratch my head the question: why a tsconfig.ts (and a package.js) wasn't chosen.
Reacted by João Ferreira, Artyom, Amer Yousuf, floratmin, Hunter Larco, Romain Laneuville, Andreas Wiesinger, Dom DiCicco and snarbles2This makes working with nested
tsconfig.json's very annoying...Reacted by Amer Yousuf, Adam, floratmin, Marc Siegel, Austin Biggs and snarbles2Monorepo plus fastify plugins becomes copy + paste hell.
Reacted by Andreas Wiesinger and IgorThe solution is to only use
typescript.compilerOptions.pathsto describe entrypoints into your monorepo packages.yes you obviously can choose to not do this and create little magical "helper aliases"... but you shouldn't.
Instead of using it to avoid using your keyboard... use it to simulate using published packages and avoiding the constant rebuilding required (or go and use preconstruct if you require babel)
- Only use paths to describe entrypoints for your monorepo packages.
- Every where else (ie inside those packages), only use relative paths.
tsconfig{ "compilerOptions": { "paths": { "@domain/foo": ["./pkgs/foo/src/index.ts"], "@domain/foo/client": ["./pkgs/foo/src/client.ts"], "@domain/foo/fs": ["./pkgs/foo/src/fs.ts"], } } }pkgs/foo/package.json{ "name": "@domain/foo", "exports": { ".": "./dist/index.js", "./client": "./dist/client.js", "./fs": "./dist/fs.js", } }If you need aliases within your packages then it's a pretty good sign that it's too big or you've got too much folder nesting going on.
Reacted by Top Master, Nils Bunger, Kasopej, Druvis Cukurs and Benedict LeeZeno Jiricek (@airtonix) No matter what "sign" that is, this is a feature request and you're not forced to use said feature, similarly, you can't force others into NOT using said feature either.
This thread shows the world how fast Microsoft handles issues, and it shows why Git has a fork feature, please some other company should fork this and rewrite TypeScript-Compiler in
Rustand/orC++please, instead of waiting years and years for Microsoft'sGorewrite.Reacted by Ryan Cavanaugh, Kasopej, Igor and Kristian Gerardsson👀 Looking forward to the next steps...
Reacted by EVA (Entity Value Attribute)
Scenario: As a user, I would like to optionally merge extended arrays in
tsconfigfiles. To do so, I would add a nested dot array["..."]reminding spread operator to the property I want to merge. Here is an example:tsconfig-base.json{ "exclude": ["**/__specs__/*"] }tsconfig-custom.json{ "extends": "./tsconfig-base.json", "exclude": [["...tsconfig-base"], "lib"] // resolved to ["**/__specs__/*"; "lib"] }Alternative: using a config
{}objecttsconfig-custom.json{ "extends": "./tsconfig-base.json", "exclude": [{ "extends": "tsconfig-base" }, "lib"] // resolved to ["**/__specs__/*"; "lib"] }