-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
tsconfig.extends
as array
#29118
Comments
please do this i have 4 config. 2 of them have duplicate json in them because of missing mixin ability |
Was there any feedback from the developers of tsconfig files? |
Some more thoughts from me: This would not be a big deal if tsconfig.js files were allowed. Currently the only workaround is to regenerate tsconfig files via a custom tool everytime the source tsconfigs change, via file watcher. I have the option to run typescript programmatically. But that is only for building stuff. The whole IDE experience however relies on actual real tsconfig files on the file system, and there is no way around that. I understand the added complexity in languages like C# where multiple inheritance is not possible. Of course specifying a string should still be possible for backwards compatibility and to hide "complexity". Also lots of people also expect an array because they are used to eslint and other tools were that is possible. I also think an array is extremely simple and intuitive to understand. It is the same as a single path, except applied multiple times. There are many options in tsconfig that are harder to understand than an extends array IMHO :) |
Does anyone see any downsides to this, apart from the amount of work it may take to develop the feature? This seems like a no-brainer to me. |
Looks like there is no point in opening feature tickets for this project. |
The issue was reopened in January of this year, but it remains a little ambiguous whether or not a PR will be accepted. |
For some reason, I'm always the guy who sets up new projects. Everytime I start a node/web/electron project, I'm looking forward to coding because I really like developing with Typescript. And then my selective memory faces the reality of tsconfig, webpack.config, rollup.config, babelrc, createReactApp and later replacing it with a manual build and everytime I wished I had not said yes because I'm so tired of this configuration hell. tsconfig is by far not the worst part of this trauma, but every time I suffer from the fact that in the end I need to make space in my brain for the full scope of tsconfig options, how they interact with every tool and the last little build pipeline screw, and I just get so much more tired every time. I understand that this config issue is not exciting or important, but it could solve a persistent headache. Why can't I tell TSC that I want a baseline of language options, a config suitable for react and webpack and be done with it? Why do I have to try chaining up configs in the proper order just to yet again conclude that I have to copy & paste it together anyway. I never got around to use snippet managers. And I'm too old to change my mind on that. Contemporary software development feels more like overlaying memory blocks in ForTRAN (I forgot the proper terminology, but I guess there are few people around who know enough to point it out) than something that deserves the attribute modern. And I'm saying this even though I deeply love Typescript. I just hate tsconfigs. I would gladly volunteer to implement it, but considering the many other TS tickets I followed and the fate of related PR's, that would just amplify my frustration. Sorry for ranting so much, I gladly accept the thumb-downs. Please note that despite the rant I really appreciate your work. Just not your horrible tsconfigs. EDIT: And I forgot to mention the plethora of death threads that I have to issue in the dev team in case someone dares so much as to even look at any of these configs much less edit them. Extension arrays have the potential to save lifes! |
@mutech i agree in principle - i've seen too many pieces of partial tsconfigs being copied around for the reasons you describe. mixins might help solving this issue. one caveat though: mixins can become quite interesting to debug once multiple ones are allowed to change the same values. to stay with OO terminology, with simple linear inheritance it's more often than not a good idea to rule out overwriting settings in a child that a parent already defines. with mixins, this is even more important to avoid difficulties in finding out where some setting value actually comes from. |
That's a very valid point. I have this very discussion in another context right now. What if a developer changes the theme color and messes up the whole App because he wants to change the appearance of a button. Not surprisingly, we are now now not using any centralised information storage to be safe from such confusions. But the thing is, no matter what precautions you take, developers are going to make mistakes, we are human and misunderstandings are not exceptions. I think that generally the best approach is to use the same or closest level of abstraction to the problem or the real world item you are working with. For TypeScript, tsconfig is reflecting reality perfectly. For a project, this is just wrong. tsconfig defines what language the project is using, well what language dialect. Which features are available, is JavaScript valid TypeScript, do we have attributes and which flavour, is the project TS strongly typed or forgiving, can we use namespaces, can we use enums and how, does every array has to have an extra comma, the list goes on and one. And if you naively choose one setting you get a bloody nose seeing weeks later that this has an impact on something you believe is utterly unrelated. It doesn't stop there. We not only define the project language we use, we also have to define the babel language, the Webpack language, the language when extracting documentation, type declarations for JS folk, another endless list. Technically, I believe it would be better to import typescript modules instead of compiling typescript down to javascript with dependencies on either external ts-runtimes or by copying js code and then using declarations to use the result of this process in a typescript client. This is however impossible, because every library uses their own variation of typescript that is very unlikely to even compile over there. If you want to specify what your typescript flavour is, you have to copy & paste your tsconfig, and in this tsconfig, you specify stuff about commas, module lookup, where to put source maps, which platform APIs are used, etc. A modular structure has the potential to organise these configurations and separate concerns. We could standardise aspects of the language and create a vocabulary such that we don't always have to talk about commas. No matter what we do, we cannot avoid difficulties when we work with complex systems, we have to face them instead and handle them in an intelligent way, something better than copy & paste. I have seen the world of Cobol and Fortran, OO was news to me, I used Smalltalk and Eiffel, Perl and Assembler and I'm still hacking and witness the new ideology of simplicity, the search for the holy single source of truth and please don't inherit stuff. But in my experience, the thing is this, people write good software when they know what they're doing. And to understand stuff, you have to focus on important aspects and avoid unnecessary complications. Then you can inherit and it's not like every kind of engineering is necessarily over-engineered. Sorry, I'm getting increasingly philosophical here, but I feel like my industry is getting too attached to simple rules being applied to complex problems. Being scared of multiple inheritance because someone once tried to write good C++ code and failed while we all have more than one parent and consider ourselves success stories is rather inconsistent. The question should not be whether this is multiple inheritance (it's not) and thus bad, the question is whether this would overall make our lives easier, which I firmly believe it would. |
Imposing a complex semantic on how configs can or can't be combined or overridden is in my opinion not a good idea for these reasons:
"extends" not supporting "mixins" is a perfect example for something being too simple to be useful, while a protectionist multiple inheritance mechanism would be too complex to be useful. As soon as you have a modular configuration, it's easy to develop and define best practices (by creating fragments that you declare fit or a specific purpose), distill which features don't and won't work together and get this topic settled once and for all. And if someone dares touching these crown jewels you can still throw coffee mugs their way. |
User defined types can be more complex then multiple inheritance of tsconfig will ever be. We don't restrict the complexity on those types. And I have had a HARD time bugfixing some complex types of mine. So why are we allowing complexity in user defined types, but not allow a array of extends in tsconfig? I think users should decide for themselves. I do not think developers should decide for users. We won't break tsconfig files, a string would still be allowed. I understand that some programming languages have opted out of multiple inheritance of classes. But this is something completely different, since it is just overriding of properties in a certain order, so where is the magic? I would like to ask for concrete examples of where multiple inheritance of tsconfig will go wrong, please. Since that's all that matters. Note: tsc can/could print resulting tsconfig files on demand, so troubleshooting should be a breeze. |
@weswigham please review this and consider this as related to #46452 as it now gets more and more relevant with the new resolve modes and if the module do use allowSyntactic or not or esInterOp or not and so on also see: #48437 which is a duplicate of this but shows a more current typescript case with 4.7 and the need to have diffrent module resolve composition sets with diffrent options. for monorepos and so on. |
A somewhat niche (but decreasingly so) use case for multiple extends is for people using TypeScript in SvelteKit. In SvelteKit, types are automatically generated for your components and pages, and have to be accessed by extending a generated tsconfig file (the generated config also gives a lot of other configurations which are necessary for development). However if you're using a monorepo to handle related yet distinct packages, you can't have both a common tsconfig and the SvelteKit generated tsconfig. This would not be an issue if instead of only permitting one extends, you were allowed several. A virtual chain of extensions could be made and analysed, where items in the array override items prior to them. I don't think it's a particularly difficult thing to do, and passing a string can work exactly the same as it does currently after multiple extends is implemented. |
In addition to @willster277's explanation I would add that this issue is not going to go away. With the advent of Turborepo, Rushjs and others...I see this as a moderate but growing need. For those of us working in larger monos this would be truly helpful. Additionally with Vercel/Next investing in SvelteKit, which is gaining growing support, I suspect you will only see more and more of this very issue popup. While things are always more involved under the hood, most are going to see this as a simple Object.assign and wonder why it doesn't already exist. While I get it's not quite that simplistic, nonetheless that's the perception. |
A basic svelte example. Replaces #1184 and #244 **NOTE**: There is no shared `ts-config` package here because of how svelte sets up it's ts-config inheritance. The base config is auto generated in a set location (`.svelte-kit`). There are a few open issues about adjusting this for better monorepo support (relevant issues: sveltejs/kit#4052, microsoft/TypeScript#29118 (comment))
Is there any input from the typescript team on whether a PR would be accepted for this issue? Is it a technical resourcing issue in getting it done or still under consideration as to whether it's worth doing? And just adding another datapoint to the pile, without this support in a monorepo context with shared tsconfig and any kind of generated project tsconfig (SvelteKit in my case), it becomes extremely painful to use Tyepscript without it. |
The most simple solution would also be to simply implement tsconfig.js call that from time to time and look if the result did change maybe expose a didChange value from time to time thats the level we need to address everything. i experimented with that via tsconfig.js => tsconfig.json and i got good results but it would be more elegant if i could avoid the filesystem writes |
The tipping-point scenario for us was the upcoming module resolution work, wherein it's likely that we'll be encouraging bundlers/etc to ship specific config subsets that describe their behavior. |
@navya9singh is making changes to make commandline options to support type that takes list or element type |
There are already command line options using lists (include/exclude), so there should be no reason to have different option types in the command line and config files. |
Looking forward to this enhancement hopefully shipping soon… 🤞 |
A basic svelte example. Replaces vercel/turborepo#1184 and vercel/turborepo#244 **NOTE**: There is no shared `ts-config` package here because of how svelte sets up it's ts-config inheritance. The base config is auto generated in a set location (`.svelte-kit`). There are a few open issues about adjusting this for better monorepo support (relevant issues: sveltejs/kit#4052, microsoft/TypeScript#29118 (comment))
Sorry if that was already explained above, but I want to be completely sure what this change brought to the table. Let's say that:
and
Then is it true that
And if I'm right then does it mean that to maintain the same behaviour for the |
No. TypeScript 4 does not set the default compiler options if you set // tsconfig.base.json
{
"compilerOptions": {
"declaration": true,
}
} // tsconfig.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {}
} // npx --package=typescript@4 -- tsc --showConfig
// npx --package=typescript@5 -- tsc --showConfig
// Both show same result:
{
"compilerOptions": {
"declaration": true
},
"files": [
"./index.ts"
]
} |
Search Terms
tsconfig extends array
Suggestion
Support defining the "extends" option as array of filenames.
would have the same result as extending
c
wherec
extendsb
andb
extendsa
.Use Cases
This would make it so much easier to compose modular configuration fragments, analogue to "presets" in babel.
Examples
Given a set of tsconfig files containing fragments:
It would be possible to combine these fragments in a way that is much more expressive and easier to
understand than flat config files.
A/tsconfig.preact.json:
A/tsconfig.react.json:
tsconfig.webpack.json
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: