-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Feature request: allow user to merge extended arrays in tsconfig files #20110
Comments
Personally, I'd sooner like to see a |
Noooooooooooooooo. |
We did talk about the OP when we first put in the configuration inheritance in place, and had a proposal of |
"Do not over-complicate the implementation with abstractions where a little copying will suffice" - Unattributed programming koan |
I 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. |
As 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. |
Sorry 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. |
@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. @mhegazy disagrees. :) |
@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. |
As I noted earlier, we have discussed such configuration inheritance use cases when we were implementing the feature; as a matter of fact @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. |
@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. |
We are always open to revisiting requests. |
Don't we have TypeScript for that? :D Thanks to By the way I wonder what is the correct way to "read" an extended config? Is this the "shortest" way?: import { parseJsonConfigFileContent, readConfigFile, sys } from 'typescript';
const path = './foo/tsconfig.json';
const { config } = readConfigFile(path, sys.readFile);
const host = {
useCaseSensitiveFileNames: false,
readDirectory: sys.readDirectory,
fileExists: sys.fileExists,
readFile: sys.readFile
};
const { options } = parseJsonConfigFileContent(
config,
host,
basename(path)
);
console.log('Parsed (!) CompilerOptions:', options); |
+1 for merge
All apps/libs In order for apps to import
It works great! But a
And I've just lost an |
@zaverden What about using the xplat architecture? Would not that be sufficient to tackle your use-case? After all, if you want to refactor modules, you simply have to rename your module and all the shared modules between your apps, so it's one additional file change per app, which IMO is a very scalable solution, but there might be a better approach. What does @weswigham think? |
@diegovincent I don't think I understand how xplat can help to address the issue. I have custom path aliases defined in So I don't understand how xplat can help me to get rid of custom path aliases on application level, when whole team use them a lot and think they are very convenient. |
@zaverden I mean their architecture just makes yourself wonder if you truly need what you are asking for. A lot of the times we all stay too long wondering if we can do something, but not if we should do it. I was just thinking, maybe all your features can probably be refactored outside of your app, or, in the case they are extremely app-specific, they can simply be refactored into Angular modules, hence you only import stuff once, then moving stuff around is just a matter of moving the module and its import. If the module is already inside your import { MyModule } from '@my-org/libs/core/my-business-domain' Which already solves your problem. My only concern is, can the experts at Microsoft or Angular or Nx or Xplat assure that it is indeed a best practice to create additional Those are my 2 cents. |
@diegovincent thank you for clarification. Indeed you are right, these custom aliases are signals that something went wrong. Unfortunately, my team did not understand these signals on earlier stages of a project. Now we develop new app with xplat-like approach (we defined our own categories and templates). But there are dozens of old-style active apps. We cannot refactor them all in one day. |
We also have the same issue described before, which means that we have a monorepo and would like to be able to extend the
I totally agree with that ! |
I wrote a utility for our organization that essentially copy/pastes
This is the utility: And here's how it manages the various tsconfig files. It only touches After implementing this, the TypeScript experience in VS Code got a lot better. Fox example, renaming a symbol "just works" across multiple dependencies. In the example repo you can rename the "utility" function and it carries over to |
More use cases for extending the
Such a "boilerplate" config may look like this:
More about this in this issue here: |
This seems to make sense for me - it seems like the @mhegazy would you reconsider your position on a code-based |
One other thing I've been watching is the new To me, it doesn't seem like it solves these Is there an alternative path forward connected to the comment about "it's likely that we'll be encouraging bundlers/etc to ship specific config subsets that describe their behavior" from @RyanCavanaugh? |
A way to merge The project structure:
Every library/app has its own tsconfig with a path alias for the libXYZ - tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"paths": {
"~/*": ["./libs/libXYZ/*"]
}
},
} All libraries are listed in the // tsconfig.paths.json
{
"compilerOptions": {
"paths": {
"@myorg/libA": ["dist/libs/libA/src/index.d.ts"],
"@myorg/libB": ["dist/libs/libB/src/index.d.ts"],
...
}
}
} The root config with all the main common settings: // tsconfig.base.json
{
"extends": ["./tsconfig.paths.json", "etc"],
"compilerOptions": {
...
},
} This setup allows you (well would allow you if it worked) to:
Spent a good hour trying to figure out why this setup wasn't working until I found this issue and realized |
It's been years, and seems code and/or And suddenly changing Solution#1 Merge mode:Add #2 Inherit placeholder:Support Inherit Example{
"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/*"]
}
}
}
#3 Version info:Optionally, add |
It doesn't seem to have been mentioned before in this thread, so thought I would add it to the list of use cases: I was quite surprised that the In our setup, we have a central repository of tsconfigs that represent either a base, a platform or a framework. The intention is that we can mix and match these configs in the Happy to open another issue if we'd like to treat these separately. |
I'd be +1 on
|
+1 on having the option to merge. |
Here to vote for the 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/*": ""
}
}
} |
Because " Hence, I prefer the RegExp filter idea that was mentioned:
Using that, we could simply use the " {
"<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: |
would 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 |
Very 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. |
We 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 https://gist.github.com/laverdet/a192df6ca10458e6fd2c2b32330c5923 |
Extending from base configs is pretty painful due to this limitation. |
Any progress on this issue ? |
Having 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. |
This makes working with nested |
Monorepo plus fastify plugins becomes copy + paste hell. |
Scenario: As a user, I would like to optionally merge extended arrays in
tsconfig
files. 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
tsconfig-custom.json
Alternative: using a config
{}
objecttsconfig-custom.json
The text was updated successfully, but these errors were encountered: