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

tsserver (vscode) does not recognize multiple tsconfig.json in the same directory #8435

Closed
tkrotoff opened this issue May 3, 2016 · 17 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@tkrotoff
Copy link

tkrotoff commented May 3, 2016

Example of file organization:

app/feature1/model.ts
             model.spec.ts
             controller.ts
             controller.spec.ts
             template.html
             documentation.md
    feature2/model.ts
             model.spec.ts
             controller.ts
             controller.spec.ts
             template.html
             documentation.md
    tsconfig.json      <-- list *.ts files + third-party *.d.ts (ex: angular.d.ts)
    tsconfig.spec.json <-- list *.spec.ts files + third-party *.d.ts (ex: jasmine.d.ts)

tsc works fine. However vscode does not properly highlight files listed in tsconfig.spec.json (like #5828).

Using TypeScript 1.8.10 and vscode 1.0

@tkrotoff tkrotoff changed the title tsserver (vscode) does not recognize several tsconfig.*.json in the same directory tsserver (vscode) does not recognize multiple tsconfig.*.json in the same directory May 3, 2016
@tkrotoff tkrotoff changed the title tsserver (vscode) does not recognize multiple tsconfig.*.json in the same directory tsserver (vscode) does not recognize multiple tsconfig.json in the same directory May 3, 2016
@mhegazy
Copy link
Contributor

mhegazy commented May 3, 2016

This behaves as intended. there is only one special tsconfig.json. the other ones can be passed explicitly to tsc, but when automatic search is done, either in tsc or in tsserver, only tsconfig.json is looked up.

@mhegazy mhegazy closed this as completed May 3, 2016
@mhegazy mhegazy added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label May 3, 2016
@tkrotoff
Copy link
Author

tkrotoff commented May 3, 2016

Ok, so with tsserver

then how can you organize code by features/components in a simple way? It is a valid use case.

TypeScript very first description line:

TypeScript is a language for application-scale JavaScript

@mhegazy
Copy link
Contributor

mhegazy commented May 3, 2016

then how can you organize code by features/components?

not sure i understand what you mean by this. if you have a tsconfig per feature/component it is going to work. what is not, is having multiple build configurations for the same feature/component in the IDE.

@tkrotoff
Copy link
Author

tkrotoff commented May 3, 2016

@mhegazy

not sure i understand what you mean by this

by features/components/modules:

app/feature1/model.ts
             model.spec.ts
             controller.ts
             controller.spec.ts
             template.html
             style.css
             feature.png
             README.md
    feature2/model.ts
             model.spec.ts
             controller.ts
             controller.spec.ts
             template.html
             style.css
             feature.png
             README.md

vs by type of files:

src/models/feature1_model.ts
           feature2_model.ts
    controllers/feature1_controller.ts
                feature2_controller.ts
    templates/feature1_template.html
              feature2_template.html

doc/feature1.md
    feature2.md

styles/feature1.css
       feature2.css

img/feature1.png
    feature2.png

test/feature1_model.spec.ts
     feature2_model.spec.ts
     feature1_controller.spec.ts
     feature2_controller.spec.ts

Link from my previous comment: https://www.google.fr/search?q=organize+code+by+feature
Examples of AngularJS articles:

Note: most articles don't mention where the tests should go because most people don't write tests and thus don't mention it.
Obviously you want your tests as close as possible to the code they test, not at the other side of your hard drive, same for your code documentation (you've recognized the 'by file type' organization here).
Writing tests and documentation is no fun, your code organization should not make it even harder else you can be sure your team won't never update the tests nor the documentation.

@mhegazy
Copy link
Contributor

mhegazy commented May 3, 2016

I still do not understand why you can not do this with one tsconfig.json per folder.

@tkrotoff
Copy link
Author

tkrotoff commented May 3, 2016

why you can not do this with one tsconfig.json per folder

Nobody wants to ship something bundled with the tests on a website, so you need 2 tsconfig.json :)

Also having 1 build for the app and 1 build for the tests helps: you can easily experiment/hack with the app code without having compile errors about the now outdated tests. (typical workflow: hack -> looks good? -> clean things up + write tests).

Sure you can have 3 tsconfig.json instead of 2:

  • one to please the IDE/tsserver
  • one to build the app code
  • one to build the tests

=> More things to maintain :/

@mhegazy
Copy link
Contributor

mhegazy commented May 3, 2016

Nobody wants to ship something bundled with the tests on a website, so you need 2 tsconfig.json :)

so why not two tsconfig.json files in two folders, i.e. src\tsconfig.json and test\tsconfig.json?

@tkrotoff
Copy link
Author

tkrotoff commented May 3, 2016

src\tsconfig.json and test\tsconfig.json

Does not solve the problem, see #5828 (my first attempt before TypeScript 1.8 came out with the tsc -project fullpath feature).

I think allowing a tsconfig.json to reference other tsconfig.json (TypeScript 2.1) will simplify things:

  • tsconfig.test.json => build the tests
  • tsconfig.app.json => build the app
  • tsconfig.json => pleases the IDE/tsserver, references tsconfig.test.json and tsconfig.app.json

You have 3 tsconfig.json files but the one for the IDE is just an empty shell that points to the others: easy to maintain.
It still feels awkward: go explain to somebody why you have 3 tsconfig.json files...

Another better (and complementary?) solution can be multiple "targets"/builds/projects inside 1 tsconfig.json file (see #1928):

{
  "compilerOptions": {
    "noImplicitAny": true,
    "removeComments": false,
    "sourceMap": true
  },
  "files": [
    "common/util.ts"
  ]
  "projects": {

    "app": {
      "compilerOptions": {
        "outFile": "app.js"
      },
      "files": [
        "feature1/model.ts",
        "feature1/controller.ts",
        "feature2/model.ts",
        "feature2/controller.ts"
      ]
    },

    "unittests": {
      "compilerOptions": {
        "outFile": "unittests.js"
      },
      "files": [
        "feature1/model.spec.ts",
        "feature1/controller.spec.ts",
        "feature2/model.spec.ts",
        "feature2/controller.spec.ts"
      ]
    },

    "e2etests": {
      "compilerOptions": {
        "outFile": "e2etests.js"
      },
      "files": [
        "feature1/e2e.spec.ts",
        "feature2/e2e.spec.ts"
      ]
    },

    "app-es3-amd": {
      "compilerOptions": {
        "target": "es3",
        "module": "amd",
        "outFile": "app-es3-amd.js"
      },
      "files": [
        "feature1/model.ts",
        "feature1/controller.ts",
        "feature2/model.ts",
        "feature2/controller.ts"
      ]
    }
  }
}
  • Only one tsconfig.json file \o/
  • IDE/tsserver always happy \o/
  • Easy to understand and scalable
  • Pass the target name to tsc otherwise all targets are compiled (default behavior)

@mhegazy
Copy link
Contributor

mhegazy commented May 3, 2016

This is not the intended use of tsconfig.json. it is not meant to be a build orchestration tool nor a solution file. a single tsconfig.json represents a single invocation to tsc.exe/tsc.js. and that is that. for more interesting build/configuration consider using other build tools e.g. MSBuild, grunt or gulp.

my recommendations for this scenario are:

  • use two tsconfig.json files, one in sources and one in tests.
  • use a build tool to ensure building the tests will build the sources, e.g. grunt/gulp
  • in your editor, once you open a file from the test directory and a file from the source directory, two projects will be loaded in memory, with Enable tsserver global operations to be performed on all projects #7353, you get the global operations like find all references, and rename working on both projects. and no need for an uber project that unify them.

@tkrotoff
Copy link
Author

tkrotoff commented May 4, 2016

consider using other build tools e.g. MSBuild, grunt or gulp [...] use a build tool to ensure building the tests will build the sources

Obviously, how can you do without? sass/less, minification, launch a server, move files around, call tsc -p...

use two tsconfig.json files, one in sources and one in tests.

Does not please the IDE, see #5828. You can check for yourself: https://github.com/tkrotoff/vscode-tsconfig.conf-issue

Anyway...

@basarat
Copy link
Contributor

basarat commented May 4, 2016

use two tsconfig.json files, one in sources and one in tests.

This is the one I'd recommend as well. The test file should be in a folder above the src. TSServer will work as it is

Project pitch

I'll work on improving the set project in alm to take more than files by tsconfig.json name at some point so it shows more than just tsconfig.json exact matches https://github.com/alm-tools/alm/blob/master/docs/features/omni-search.md#project-search
🌹

@mhegazy
Copy link
Contributor

mhegazy commented May 4, 2016

Does not please the IDE, see #5828. You can check for yourself: https://github.com/tkrotoff/vscode-tsconfig.conf-issue

I see now, so you want the tests to be next to your app, but not in the production release. so why not have two tsconfig.json, at the root, one tsconfig.json (includes all files, tests and sources), and another one tsconfig.production.json that excludes the test files?

@tkrotoff
Copy link
Author

tkrotoff commented May 5, 2016

you want the tests to be next to your app, but not in the production release

YES! :-)

one tsconfig.json (includes all files, tests and sources), and another one tsconfig.production.json that excludes the test files?

Exactly what I do now

no need for an uber project that unify them

Multiple "targets"/builds/projects inside 1 tsconfig.json has already been proposed: #1928.
This + allowing tsconfig.json to reference other tsconfig.json files cleanly solved all use cases.

@mhegazy
Copy link
Contributor

mhegazy commented May 5, 2016

Multiple "targets"/builds/projects inside 1 tsconfig.json has already been proposed: #1928.

I do not think we will be parametrizing tsconfig.json any time soon, for the same reason i listed earlier. tsconfig.json is just an easy way to call tsc.exe with a punch of parameters. if you want to do something fancier, you should use a build system/ solution file (whatever that would be in your editor).

This + allowing tsconfig.json to reference other tsconfig.json files cleanly solved all use cases.

you can see my argument against using tsconfig.json as a build manager in #3469 (comment).

@simonbuchan
Copy link

extends works for maintaining multiple build files, but there's still an editor issue. Jetbrains (IntelliJ / WebStorm) recently implemented IDE support for selecting the appropriate tsconfig file by exclude / include / files: see the blog post and bug

A rough description, they have configurable file name patterns for config files, expanding the lookup for tsconfig.json (say, to tsconfig.*.json - it seems they reverted the default pattern list since the post to just tsconfig.json again), and for each edited file select the first found config where the paths match.

Therefore, you could have, for example:

  • tsconfig-base.json with common settings (not directly used)
  • tsconfig.web.json with lib: ['dom'], types: [] and include: ['src'], exclude: ['*.test.ts', '**/__mocks__']
  • tsconfig.test.json with types: ['node', 'jest'] and include: ['src/**/*.test.ts', 'src/**/__mocks__']
  • tsconfig.scripts.json with types: ['node'] and exclude: ['node_modules', 'src']

And have the editor know that, e.g. describe() is invalid in scripts/start.ts, and window.location is invalid in src/App.test.ts

@jdforsythe
Copy link

jdforsythe commented Jun 22, 2018

This is an incredibly annoying problem.

I understand the argument that tsc shouldn't be used as a build tool, and tsconfig.json shouldn't be used as build configuration. But it is because MS is using tsc as a linter that this issue is a problem for us.

Real-world example:

  • compiler options in /tsconfig.json
  • source code in /src/**/*.ts
  • tests in /src/**/*.spec.ts
  • /tsconfig.json obviously excludes *.spec.ts so they aren't compiled into /lib and distributed to npm.
  • something.spec.ts uses decorators (mocha-typescript) - VSCode gives many "Experimental support for decorators is a feature that is subject..."

We will not put our tests in a separate /tests folder because they are not visible. When specs are beside the files they're testing, it is easy to see when tests are missing or haven't been updated. So with the spec files in the same folder as the source code, how exactly would one go about telling tsc/VSCode that there are different requirements for spec files?

I have tried putting a spec-specific tsconfig.json in the /src/ folder and leaving the main tsconfig.json in the root. That didn't work.

I can see that this isn't necessarily a typescript issue - for me it's more of a VS Code configuration issue - I should be able to specify which tsconfig matches which files - but I think the request here is that it "just work" because the files themselves already have the matchers needed to decide which config to use. There would just need to be some way to register all the config files or some naming convention, etc.

I'm more in favor of a VSCode config file that would register my two tsconfig.json files and based on the include/exclude settings in the file choose the proper config to pass to tsc for the file I'm looking at.

I don't have the perfect solution, but I know that putting things like this at the top of all my spec files:

// - tests require packages from devDependencies
// - mocha has side-effects
// - chai has odd syntax
/* tslint:disable no-implicit-dependencies no-import-side-effect no-unused-expression function-name max-classes-per-file no-any */

shouldn't be necessary. And looking at this makes the problems panel in VS Code useless.

image

lobsterkatie added a commit to getsentry/sentry-javascript that referenced this issue Jun 2, 2022
It is well-documented (see 1-6 below) that VSCode doesn't support setups like ours, where multiple tsconfig files coexist in a single directory. Strangely, though, it is only recently that this has become a problem, with VSCode at random intervals forgetting that it's ever heard of `expect` or `describe` (because it's not seeing `tsconfig.test.json`, but taking a while to realize it).

There is an open issue[7] tracking the addition of support for this, but it's been open for a long time, with little movement. In the meantime, this solves the problem by adding placeholder `test/tsconfig.json` files to each package, each pointing to its corresponding `tsconfig.test.ts` file. I went with this approach over simply moving and renaming the existing test tsconfigs because this allows us to stay consistent in having all flavors of tsconfig for a package live at the package root level, and provides an easy way to reverse this workaround, should VSCode ever fix the underlying problem.

[1] angular/angular-cli#5175
[2] microsoft/TypeScript#49210
[3] microsoft/vscode#107750
[4] microsoft/vscode#12463
[5] sillsdev/bible-karaoke#175
[6] microsoft/TypeScript#8435
[7] microsoft/TypeScript#33094
lobsterkatie added a commit to getsentry/sentry-javascript that referenced this issue Jun 3, 2022
It is well-documented (see 1-6 below) that VSCode doesn't support setups like ours, where multiple tsconfig files coexist in a single directory. Strangely, though, it is only recently that this has become a problem, with VSCode at random intervals forgetting that it's ever heard of `expect` or `describe` (because it's not seeing `tsconfig.test.json`, but taking a while to realize it).

There is an open issue[7] tracking the addition of support for this, but it's been open for a long time, with little movement. In the meantime, this solves the problem by adding placeholder `test/tsconfig.json` files to each package, each pointing to its corresponding `tsconfig.test.ts` file. I went with this approach over simply moving and renaming the existing test tsconfigs because this allows us to stay consistent in having all flavors of tsconfig for a package live at the package root level, and provides an easy way to reverse this workaround, should VSCode ever fix the underlying problem.

[1] angular/angular-cli#5175
[2] microsoft/TypeScript#49210
[3] microsoft/vscode#107750
[4] microsoft/vscode#12463
[5] sillsdev/bible-karaoke#175
[6] microsoft/TypeScript#8435
[7] microsoft/TypeScript#33094
@jeengbe
Copy link

jeengbe commented Aug 26, 2022

Is there any option of rethinking this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

6 participants