镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Feature request: allow user to merge extended arrays in tsconfig files #20110

Description

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
{
  "exclude": ["**/__specs__/*"]
}
tsconfig-custom.json
{
  "extends":  "./tsconfig-base.json",
  "exclude": [["...tsconfig-base"], "lib"] // resolved to ["**/__specs__/*"; "lib"]
}

Alternative: using a config {} object

tsconfig-custom.json
{
  "extends":  "./tsconfig-base.json",
  "exclude": [{ "extends": "tsconfig-base" }, "lib"] // resolved to ["**/__specs__/*"; "lib"]
}

Activity

  1. weswigham commented on Nov 17, 2017

    @weswigham
    Member

    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".

  2. mhegazy commented on Nov 17, 2017

    @mhegazy
    Contributor

    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.

  3. mhegazy commented on Nov 18, 2017

    @mhegazy
    Contributor

    We did talk about the OP when we first put in the configuration inheritance in place, and had a proposal of extends and overwrites to be two different behaviors for cases like these.. but in the end we chose to avoid complexity and just go with extends meaning overwrite. 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.

  4. weswigham commented on Nov 18, 2017

    @weswigham
    Member

    "Do not over-complicate the implementation with abstractions where a little copying will suffice" - Unattributed programming koan

  5. jsamr commented on Nov 18, 2017

    @jsamr
    Author

    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.

  6. jsamr commented on Nov 18, 2017

    @jsamr
    Author

    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.

  7. weswigham commented on Nov 18, 2017

    @weswigham
    Member

    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.

  8. jsamr commented on Nov 18, 2017

    @jsamr
    Author

    Wesley 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) ?

  9. weswigham commented on Nov 18, 2017

    @weswigham
    Member

    I, personally, would prefer a code file. Mohamed Hegazy (@mhegazy) disagrees. :)
    As I said, strong opinions.

  10. jsamr commented on Nov 18, 2017

    @jsamr
    Author

    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.

  11. mhegazy commented on Nov 18, 2017

    @mhegazy
    Contributor

    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.

  12. mhegazy commented on Nov 18, 2017

    @mhegazy
    Contributor

    As 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.

  13. jsamr commented on Nov 19, 2017

    @jsamr
    Author

    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.

  14. 25 remaining items

  15. lobsterkatie commented on Apr 5, 2023

    @lobsterkatie

    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.
  16. toantd90 commented on May 2, 2023

    @toantd90

    +1 on having the option to merge.

  17. vinciest commented on May 8, 2023

    @vinciest

    Here 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/*": ""
        }
      }
    }
  18. top-master commented on May 18, 2023

    @top-master

    Because "<inherit>" is not just for "paths", the mentioned empty-string or null may 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 tell TSC that 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/8740349

  19. bneigher commented on Jun 1, 2023

    @bneigher

    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

  20. laurencefass commented on Mar 27, 2024

    @laurencefass

    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.

  21. laverdet commented on Mar 27, 2024

    @laverdet
    Contributor

    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 path and references in each tsconfig.json to point at the required packages.

    https://github.com/proxy/gist.github.com/laverdet/a192df6ca10458e6fd2c2b32330c5923

  22. clicktodev commented on May 27, 2024

    @clicktodev

    Extending from base configs is pretty painful due to this limitation.
    Would appreciate some movement on this by the TS team.

  23. eternal-eager-beaver commented on Jun 24, 2024

    @eternal-eager-beaver

    Any progress on this issue ?

  24. gipo355 commented on Jul 6, 2024

    @gipo355

    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.

  25. on3dd commented on Jul 18, 2024

    @on3dd

    This makes working with nested tsconfig.json's very annoying...

  26. floratmin commented on Sep 12, 2024

    @floratmin

    Monorepo plus fastify plugins becomes copy + paste hell.

  27. airtonix commented on Mar 13, 2025

    @airtonix

    The solution is to only use typescript.compilerOptions.paths to 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)

    1. Only use paths to describe entrypoints for your monorepo packages.
    2. 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.

  28. top-master commented on Apr 7, 2025

    @top-master

    Zeno 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 Rust and/or C++ please, instead of waiting years and years for Microsoft's Go rewrite.

  29. tofrankie commented on May 21, 2026

    @tofrankie

    👀 Looking forward to the next steps...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions