bluprince13
bluprince13

Reputation: 5001

Why does VSCode not pick up path aliases in tsconfig?

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.

Upvotes: 23

Views: 33900

Answers (3)

yohanes
yohanes

Reputation: 2675

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

Upvotes: 0

Jeffrey Maxwell
Jeffrey Maxwell

Reputation: 524

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.

Upvotes: 39

Guerric P
Guerric P

Reputation: 31825

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

Upvotes: 3

Related Questions