Why does VSCode not pick up path aliases in tsconfig?
Asked Answered
C

3

19

I had a jsconfig.json which I replaced with a tsconfig.json. Following the replacement, VSCode doesn't pick up path aliases and reports an import error:

Example:

Cannot find module '@Components/Title' or its corresponding type declarations.ts(2307)

jsconfig.json

// https://code.visualstudio.com/docs/languages/jsconfig

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@Components/*": ["./src/components/*"],
            "@Modules/*": ["./src/modules/*"],
            "@Styles/*": ["./src/styles/*"],
            "@Content/*": ["./src/content/*"],
            "@Apps/*": ["./src/apps/*"]
        }
    },
    //Add any build/compiled folders here to stop vscode searching those
    "exclude": ["node_modules", "build"]
}

tsconfig.json

// https://code.visualstudio.com/docs/languages/jsconfig
{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@Components/*": ["./src/components/*"],
            "@Modules/*": ["./src/modules/*"],
            "@Styles/*": ["./src/styles/*"],
            "@Content/*": ["./src/content/*"],
            "@Apps/*": ["./src/apps/*"]
        },
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": false,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "incremental": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve"
    },
    "exclude": ["node_modules", "build"],
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

Update 1: I only have this issue with files ending in .js. If I rename them to .ts everything works fine. Weirdly enough, if I rename the file back to .js and restart VSCode, the errors don't show up in the file anymore.

Certify answered 22/11, 2021 at 22:3 Comment(4)
usually when i run into this a close + re-open of code does it for me; have you tried that?Bioscope
Yup, many times.Certify
Have you tried removing the leading ./ from your paths?Drank
@Drank just gave that a go. It didn't work.Certify
D
34

The tsconfig configuration will only apply to files matched by the "include" option and not excluded by the "exclude" option. Your "include" option only matches .ts and .tsx files, but not .js files

Add "**/*.js" to the list of included globs and it should work.

Dermatome answered 29/11, 2021 at 0:14 Comment(3)
I have added this pattern to tsconfig.spec.json and nothing is changed. What can go wrong?Yonit
BTW, this may be a different question: because relative paths are not visible in my project based on angular 13 (the same error)Yonit
You're a life saver! In my cases I needed to add src/**/index.ts, to detect barrel modules onlyNatch
T
2

The problem is that TypeScript's compiler preserves the paths as they are written in the source, as you can see in this GitHub issue, which makes tsc unusable for your use case.

As you are apparently building a web application, I'll provide a minimal solution based on Webpack, one of the most popular bundlers for the web.

.
├── src
│   ├── components
│   │   └── component.ts
│   └── index.ts
├── package.json
├── tsconfig.json
└── webpack.config.js

src/index.ts

import { Component } from '@Components/component';
Component.log();

src/components/component.ts

export class Component {
    static log() {
        console.log("test");
    }
}

package.json

{
  "name": "70072923",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "devDependencies": {
    "ts-loader": "^9.2.6",
    "tsconfig-paths-webpack-plugin": "^3.5.2",
    "typescript": "^4.5.2",
    "webpack": "^5.64.4",
    "webpack-cli": "^4.9.1"
  },
  "scripts": {
    "build": "webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

tsconfig.json

{
    "compilerOptions": {
        "baseUrl": "src",
        "paths": {
            "@Components/*": ["components/*"],
        },
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": false,
        "forceConsistentCasingInFileNames": true,
        "incremental": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "jsx": "preserve"
    },
    "exclude": ["node_modules", "build"],
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

webpack.config.js

const path = require('path');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
    entry: './src/index.ts',
    resolve: {
        extensions: ['.ts'],
        plugins: [
            new TsconfigPathsPlugin,
        ]
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
};

Build the project with npm run build, which outputs a single minimal self-contained file ready to execute:

dist/bundle.js

(()=>{"use strict";(class{static log(){console.log("test")}}).log()})();

Full project here: https://github.com/Guerric-P/Webpack-and-TypeScript-path-mappings

Trinee answered 28/11, 2021 at 19:37 Comment(3)
Appreciate you taking the time to explain. I'm sorry I didn't make my question clearer though - I'm not having any problem executing my code. The error I get is purely on VSCode when I look at the file.Certify
I did realise something from your package though. You have given your index file a .ts ending. VSCode recognises '@Components/component' whilst this is the case. However, if I change the file ending to .js it throws the same error!Certify
You'll never be able to import a TypeScript module in a JavaScript module because JavaScript doesn't know TypeScript at all. As TypeScript is a superset of JavaScript, any JavaScript file is valid as TypeScript (as long as you didn't set options like noImplicitAny, noImplicitReturns, etc.) so the best thing you could do is rename all of your .js files to .ts instead of having an hybrid project like you seem to have.Trinee
B
0

In my case, the aliases can not be read by vs code on Jest extension during the test but there is no problem with yarn test.

FAIL  src/components/main/index.spec.tsx
  ● Test suite failed to run

    Cannot find module '@test' from 'src/components/main/index.spec.tsx'

    > 1 | import { render } from "@test";
        | ^
      2 |
      3 | import { Main } from "./index";
      4 |

The solution is add a settings.json in .vscode folder ar root directory:

// .vscode/settings.json
{
  "jest.jestCommandLine": "yarn test"
}
Brandenburg answered 11/9, 2022 at 4:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.