Skip to content
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

references are not inherited in tsconfig.json #27098

Open
borekb opened this issue Sep 14, 2018 · 19 comments
Open

references are not inherited in tsconfig.json #27098

borekb opened this issue Sep 14, 2018 · 19 comments
Assignees
Labels
Docs The issue relates to how you learn TypeScript
Milestone

Comments

@borekb
Copy link

borekb commented Sep 14, 2018

TypeScript Version: 3.1.0-dev.20180914

Search Terms: tsconfig.json extends references inheritance

It seems that the references key is not inherited via the extends mechanism, which surprised me because the handbook doesn't mention anything special about it.

Demo:

tsconfig.base.json:

{
  "references": [
    { "path": "./some/other/project" }
  ],
  "compilerOptions": {
    "declaration": true,
    "composite": true
  }
}

tsconfig.doesnt-work.json:

{
  "extends": "./tsconfig.base.json"
}

Building tsconfig.doesnt-work.json doesn't build the reference:

$ tsc -b -f -d tsconfig.doesnt-work.json
[11:12:13] A non-dry build would build project 'C:/demo/tsconfig.doesnt-work.json'

tsconfig.works-but-duplicates-references.json:

{
  "extends": "./tsconfig.base.json",
  "references": [
    { "path": "./some/other/project" }
  ],
}

This is a correct build but I had to duplicate the references key:

$ tsc -b -f -d tsconfig.works-but-duplicates-references.json
[11:12:13] A non-dry build would build project 'C:/demo/tsconfig.works-but-duplicates-references.json'
[11:12:13] A non-dry build would build project 'C:/demo/some/other/project/tsconfig.json'
@RyanCavanaugh RyanCavanaugh added Working as Intended The behavior described is the intended behavior; this is not a bug Bug A bug in TypeScript Docs The issue relates to how you learn TypeScript and removed Working as Intended The behavior described is the intended behavior; this is not a bug labels Oct 1, 2018
@RyanCavanaugh
Copy link
Member

This is the intended behavior but we need to document it

@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.3 milestone Oct 9, 2018
@RyanCavanaugh RyanCavanaugh removed Bug A bug in TypeScript labels Oct 18, 2018
@NoelAbrahams
Copy link

@RyanCavanaugh, what was the reasoning behind disallowing inheritance of the "reference" setting? In the old <reference> tag set-up all references of the "base" project were automatically inherited by the "client" project.

IMO that seemed to be the outcome of least surprise.

@jonaskello
Copy link

I tried to use inheritance of references section to setup a second tsconfig.json for production builds (without sourcemaps etc.). Since there is no inheritance I need to duplicate the refrences section. Perahps I'm not doing the right solution for this scenario? How would you handle a separate production build with project references?

@ggradnig
Copy link

ggradnig commented May 19, 2019

@RyanCavanaugh, still curious about the reasoning behind this design decision.

I have a use case where I need to switch the module system from es6 to commonjs for my karma-typescript tests. This is easily done by extending the original tsconfig, changing this option and referencing the extended tsconfig in the karma config. But by doing so, all the project references are lost.

While there may be reasons for not wanting to extend this attribute, I think there are also legitimate reasons for doing so. Copying the references is error-prone, people forget about it. Maybe you can find a way to allow this in a future version. Thanks :)

@RyanCavanaugh
Copy link
Member

For some hierarchy

A
⬆
B
⬆
C

B could be, for example:

  • An opaque library that doesn't intend to expose its reliance on A to its consumer C and leaks no types from A
  • A helper library that adds additional A-related functionality that C might want to use

If references are inherited, then the first scenario is impossible to do.

If they're not inherited, then you can pick which you mean from C's perspective.

@MeirionHughes
Copy link

MeirionHughes commented Jun 29, 2019

Got caught by this. In my setup I have: tsconfig.json and tsconfig.build.json per package. the first is for testing (via mocha + ts-node) and the second is derived from the first, but altered for the distribution build. Without inheritance of references I now have to duplicate them in both.

I don't understand why you can't, in an inherited tsconfig, just set the 'references' to an empty array in order to override the inheritance (completely).

perhaps introducing a keyword to signal intent might be the way to go?

i.e.

"references": [   
    "inherit",
    {
      "path": "../some-extra-dep/tsconfig.json"
    }
]

@Adamfsk
Copy link

Adamfsk commented Sep 4, 2019

@RyanCavanaugh Rather than having an extra tag in references, why not optionally allow references to be placed into a separate json file and then be refer to it in the config?

That way cases where people specifically want to list their references in a single location and share those references between two or more tsconfig.json files, they can do so without impacting those that might be affected the proper functioning of your first scenario above?

@zbigg
Copy link

zbigg commented Dec 4, 2019

@RyanCavanaugh Thanks for explanation, but I'm not sure if expected behavior and explanation provided aligns with common understanding of what "extends" mean in scope of configuration.

The example you've provided make perfect sense if A, B, C would be libraries and edges are use relations, which should be private and that's how it works in proper dependency resolution systems.

Whereas, when it comes to configuration - at least pople in this thread - inheritance means "just" take all the props from parent config, so basic "public" inheritance like we experience with Typescript extends and/or _.merge.

So, summarizing design you're referring IMHO conflicts with common understanding of inheritance in configuration systems.

Is there chance to have workaround? (given that - assuming from your comment - current behavior is already set in stone).

@Bessonov
Copy link

Bessonov commented Dec 4, 2019

I support the opinion, that current inheritance model isn't optimal.

Because tsconfig.json is a plain json file (very pity!), there is no sophisticated way to workaround it. Just for simply cases for monorepos I would like to promote my alpha set-project-references helper. It doesn't help with inheritance, but makes life with project references easier.

@dfee
Copy link

dfee commented Mar 7, 2020

^^ Documented this as it bit me hard tonight.

@laszlopandy
Copy link

In the handbook it says:

files, include and exclude from the inheriting config file overwrite those from the base config file.

Following the principle of lease surprise, references should also inherit and overwrite those from the base config file.

Regarding what Ryan said:

An opaque library that doesn't intend to expose its reliance on A to its consumer C and leaks no types from A
...
If references are inherited, then the first scenario is impossible to do.

Is it still impossible if we allow references to override even if it's empty?

{
    "extends": "./tsconfig-other.json",
    "references": [],
}

@silasdavis
Copy link

silasdavis commented May 28, 2020

Surprised++

The hierarchy/hiding argument seems a bit weak to me. Let's make those edge cases not use inheritance and just copypasta rather than changing what inheritance means structurally.

I am also trying to create a production build and avoid to compiling tests files that depend on test packages. If I exclude test files from my normal tsconfig that breaks other things (like IDEs) so I am attempting to write a production.tsconfig.json that has the necessary exclusions but otherwise does want the primary does.

martijnwalraven added a commit to apollographql/federation that referenced this issue Feb 4, 2021
Unfortunately, we need an additional `tsconfig.json` per `__tests__` directory to satisfy VS Code due to microsoft/vscode/#12463.

I tried having these extend the `tsconfig.test.json` in their respective packages, but it turns out `references` are not inherited (see microsoft/TypeScript#27098).
@lukebelbina
Copy link

I'll jump in this and bump this issue. I have a tsconfig.build.json to exclude test files from builds and expected references to inherit as this isn't clearly documented.

It isn't particularly optimal to duplicate the references in tsconfig.json and tsconfig.build.json but seems like that's the only working solution currently?

@alexpusch
Copy link

this is my unfortunate workaround for this issue:
A script that copies tsconfig, adds the tests folder into the exclude list and runs tsc on this new config file

It would be really nice to get a real solution for this.

const path = require("path");
const fs = require("fs");
const spawn = require("child_process").spawn;

const tsConfigPath = path.join(process.cwd(), "tsconfig.json");
const tsConfig = require(tsConfigPath);
tsConfig.exclude = tsConfig.exclude ?? [];
tsConfig.exclude.push("src/test");

const prodTsPath = "tsconfig.prod.json";

fs.writeFileSync(prodTsPath, JSON.stringify(tsConfig, null, 2));

const tscProcess = spawn("tsc", ["--build", prodTsPath], { cwd: process.cwd() });
tscProcess.stdout.pipe(process.stdout);
tscProcess.stderr.pipe(process.stderr);

tscProcess.on("close", (code) => {
  fs.rmSync(prodTsPath);

  setImmediate(process.exit(code));
});

@deanhiller
Copy link

seems to be best monorepo setup I have found to date for typescript. This would be amazing if fixed. Reference blog that refers to this bug -> https://blog.ah.technology/a-guide-through-the-wild-wild-west-of-setting-up-a-mono-repo-with-typescript-lerna-and-yarn-ed6a1e5467a

@DesignByOnyx
Copy link

This one just bit me hard. And since it has been this way for years there's no way to roll it back in. This is a real bummer because separate build/test/lint configs are more necessary than not, and generally they all extend a base config.

Maybe the "extends" property can accept an object with an includeReferences property which defaults to false to match the current behavior. This could also work with the new array format for extends:

{
  "extends": {
    "path": "../path/to/project",
    "includeReferences": true
  }
}

@githorse
Copy link

githorse commented Jul 21, 2023

I have dozens of packages in my monorepo, and I want to exclude test files from my production builds. So I need dozens of tsconfig.build.json files alongside my tsconfig.json files to specify the excluded tests -- but now I have to specify those dozens of lists of project references twice. This design pretty well guarantees I will trip myself up over and over by forgetting to add something in the second file.

Would definitely like to understand better why the references can't be inherited ...

timolegros added a commit to hicommonwealth/commonwealth that referenced this issue Apr 19, 2024
timolegros added a commit to hicommonwealth/commonwealth that referenced this issue Apr 25, 2024
* update tsconfig configuration in `/model`

* update tsconfig configuration in `/core`

* update tsconfig configuration in `/chains`

* update tsconfig configuration in `/adapters`

* update tsconfig configuration in `shared`

* update tsconfig configuration in `logging`

* `packages/commonwealth` tsconfig update + copy `references` to build tsconfig (microsoft/TypeScript#27098)

* specify tsconfig.build.json in references

* discobot and snapshot tsconfig.build.json updates

* remove test from includes (follow-up PR)

* merge resolution

* merge resolution

* remove "test" from include in snapshot

* leaner tsconfig

---------

Co-authored-by: rotorsoft <rotorsoft@outlook.com>
timolegros added a commit to hicommonwealth/commonwealth that referenced this issue Apr 25, 2024
* update tsconfig configuration in `/model`

* update tsconfig configuration in `/core`

* update tsconfig configuration in `/chains`

* update tsconfig configuration in `/adapters`

* update tsconfig configuration in `shared`

* update tsconfig configuration in `logging`

* `packages/commonwealth` tsconfig update + copy `references` to build tsconfig (microsoft/TypeScript#27098)

* specify tsconfig.build.json in references

* discobot and snapshot tsconfig.build.json updates

* remove test from includes (follow-up PR)

* merge resolution

* merge resolution

* remove "test" from include in snapshot

* leaner tsconfig

* remove `includes` from lib tsconfigs + fix `/adapters/test/` types

---------

Co-authored-by: rotorsoft <rotorsoft@outlook.com>
timolegros added a commit to hicommonwealth/commonwealth that referenced this issue Apr 25, 2024
* update tsconfig configuration in `/model`

* update tsconfig configuration in `/core`

* update tsconfig configuration in `/chains`

* update tsconfig configuration in `/adapters`

* update tsconfig configuration in `shared`

* update tsconfig configuration in `logging`

* `packages/commonwealth` tsconfig update + copy `references` to build tsconfig (microsoft/TypeScript#27098)

* specify tsconfig.build.json in references

* discobot and snapshot tsconfig.build.json updates

* remove test from includes (follow-up PR)

* merge resolution

* merge resolution

* remove "test" from include in snapshot

* model test type fixes

* leaner tsconfig

---------

Co-authored-by: rotorsoft <rotorsoft@outlook.com>
timolegros added a commit to hicommonwealth/commonwealth that referenced this issue Apr 25, 2024
* update tsconfig configuration in `/model`

* update tsconfig configuration in `/core`

* update tsconfig configuration in `/chains`

* update tsconfig configuration in `/adapters`

* update tsconfig configuration in `shared`

* update tsconfig configuration in `logging`

* `packages/commonwealth` tsconfig update + copy `references` to build tsconfig (microsoft/TypeScript#27098)

* specify tsconfig.build.json in references

* discobot and snapshot tsconfig.build.json updates

* remove test from includes (follow-up PR)

* merge resolution

* merge resolution

* remove "test" from include in snapshot

* update discord-bot base tsconfig

* last discord bot fixes

* snapshot fixes

* remove snapshot tsc-alias

* clean snapshot dependencies

* leaner tsconfig

* move tsx to devDep

---------

Co-authored-by: rotorsoft <rotorsoft@outlook.com>
@jtwebman
Copy link

jtwebman commented Nov 2, 2024

I think this is dumb. Why have references at all! Instead just look at the node_modules folders and go up the tree like node does. Then all these workspaces would just work without having to manually add references or even worse add some huge library like Nx to manage it all. It is like they want to make it as complex as possible.

@cantecim
Copy link

Oh god... This should be implemented.. Any update on this is it considered or not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docs The issue relates to how you learn TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.