Vscode TS language features unavailable when tests/** are not included in the tsconfig
Asked Answered
C

3

9

I would like my typescript tests to receive linting, code completion, vscode intellisense (ts language features) when the test folder is adjacent to the src. I do NOT want the tests to transpile when I build my typescript project.

My typescript node project is structured like this:

.    
├── server
│   │ 
│   │    
│   ├── src
│   │   │
│   │   └── app.ts
│   ├── test
│   │   │
│   │   └── app.test.ts
│   ├── node_modules/
│   ├── package-lock.json
│   ├── package.json
│   ├── tslint.json
│   └── tsconfig.json
├── front_end/
└── README.md

With my tsconfig:

{
  "compilerOptions": {
    "baseUrl": ".",
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "dist",
    "sourceMap": true,
    "strict": true,
    "target": "ESNext",
    "paths": {
      "*": ["node_modules/*"]
    }
  },
  "include": ["src/**/*"]
}

When I navigate to my test files in vscode, the vscode language feature wont recognize types and packages installed in node_modules. SURPRISINGLY, if I open vscode only in the server folder (as you can see from my folder structure server is not the root), the language features work 🧐.

The tests use ts-jest to run so the tsc is not needed here. Would it be better practice to extend a tsconfig.json for tests 🤔?

Is this something that can be fixed in the settings or should I submit a bug to https://github.com/microsoft/vscode/issues/new/choose.

Casias answered 31/3, 2020 at 3:37 Comment(0)
C
15

Vscode has a problem with a one root tsconfig file. An adjacent test folder to src will use the tsconfig (added in this pull request) however it won't work if the folder you open is one directory above it (for example if you have a server & client folder). A solution is being tracked in this issue: https://github.com/Microsoft/vscode/issues/12463.

In addition, if you want to upgrade to eslint (tslint is deprecated), the typescript parser will also force you to add a tsconfig file to the test folder if you wish to keep the test folder excluded in the main tsconfig. Link to eslint multi tsconfig docs.

The easy solution is to use two extra tsconfigs. One for the linter tsconfig.eslint.json and one for tests inside the test folder: test/tsconfig.json with the following content:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "noEmit": true
  },
  "include": ["./**/*"]
}

Not elegant but a better solution does not exist at this moment.

Casias answered 11/4, 2020 at 6:42 Comment(6)
Can you please explain in more details what should be in tsconfig.tests.json and how should it be related to the main tsconfig.json in your answer?Dudek
@Dudek Actually what I did is in the /test folder (that is adjacent to the /src folder) I called the file tsconfig.json and this is what it looks like: gist.github.com/Shahaed/9661cf6320e7bb60de828138ef35a856 That seems to work. In the root (one level up from this) there is a tsconfig.json and tsconfig.eslint.jsonCasias
Thank you very much. Actually, I have instinctively come to the same solution. However I had to include the source folder ("include": [".", "../src"]) in the test/tsconfig.json file to make auto import work in VSCode: prntscr.com/vkmytx.Dudek
@akd interesting, I get auto imports to work and I didn't need that. It's all a black box to me at this point.Casias
Thank you, thank you, thank you so much for this!Risotto
@Casias i have an additional issue of getting error #70070329Evenings
I
0

I don't have my computer to test this but I think you just need to add the following code to your ts json file.

"exclude": [
        "node_modules",
        "**/*.test.ts"
    ]

Break down: Exlude ** all folders / * all ts files with .test in them.

if you're not using node then you can omit the node_modules part. But I want it in my answer in case someone who is using node copies the exclude. Defaultly node_modules is excluded but adding more modifiers can over write that.

good luck.

Hope that's what you're looking for.

Institutionalize answered 31/3, 2020 at 3:50 Comment(1)
Exclude is not needed here since the tsc will NOT compile the tests.Casias
F
0

Yes, you can extend your tsconfig so that you have a common one, a production one and a development one. In our case, we have this:

tsconfig.common.json - contains all the settings shared by development and production.

tsconfig.json - the development version that includes tests:

{
    "extends": "./tsconfig.common",
    "exclude": ["bin", "node_modules"]
}

tsconfig.prod.json - the production version that excludes the tests.

{
    "extends": "./tsconfig.common",
    "exclude": ["bin", "node_modules", "tests", "**/*.spec.ts"]
}

Then with our webpack.config, we have a similar setup:

webpack.common.js - contains all the settings shared by development and production

webpack.dev.js - use the development tsconfig:

rules: [
        {
            test: /\.ts$/,
            exclude: [/bin/, /node_modules/],
            include: /ClientApp/,
            loader: 'ts-loader',
            options: {
                appendTsSuffixTo: [/\.vue$/],
                configFile: 'tsconfig.json'
            }
        }
    ]

webpack.prod.js - uses the production tsconfig:

rules: [
        {
            test: /\.ts$/,
            exclude: [/bin/, /node_modules/],
            include: /ClientApp/,
            loader: 'ts-loader',
            options: {
                appendTsSuffixTo: [/\.vue$/],
                configFile: 'tsconfig.prod.json'
            }
        }
    ]

And lastly, the package.json file has the following in the scripts section:

scripts: {
    "dev": "webpack --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js",
}

Hope that helps you.

Fibro answered 31/3, 2020 at 3:56 Comment(1)
While a good solution (I've done this in the past), a tsconfig for a folder that won't be ever be compiled seems not needed. Since our test runner is ts-jest, our tests should just need linter coverage.Casias

© 2022 - 2024 — McMap. All rights reserved.