tsconfig paths not working

TypescriptAliasTsconfigtypescript2.9

Typescript Problem Overview


I'm trying to do something very similar to the jquery path example in the documentation, but TS keeps throwing TS2307 (webpack compiles fine):

"compilerOptions": {
    "baseUrl": "./src",
    "paths": {
        "@client": [
            "client",
        ],
        "@suir": [
            "../node_modules/semantic-ui-react/dist/commonjs", // not working
        ],
    },
    // …
},
"include": [
    "*.d.ts",
    "client/**/*",
    "../node_modules/semantic-ui-react", // is this necessary?
],

Changing baseUrl to "." and updating includes and paths makes no difference (@client continues to work and @suir continues to not work).

Changing "@suir" to "@suir/" or "@suir/*" (and appending /* to its value) also makes no difference.


The reason I'm doing this is to simplify my imports (I'm specifying them explicitly instead of pulling named exports from the bundle in order to reduce my vendor bundle size—saves about 1 MB):

import Button from 'semantic-ui-react/dist/commonjs/elements/Button'; // works

import Button from '@suir/elements/Button'; // not found

Typescript Solutions


Solution 1 - Typescript

I have no idea why this is now working on the eleventh time I tried (yet didn't the first 10), but the /* seems to be the secret sauce, and the example in the docs is apparently pointing to a specific file (and the file extension is omitted).

{
    "compilerOptions": {
        "baseUrl": "./src", // setting a value for baseUrl is required
        "moduleResolution": "node", // was not set before, but is the default
        "paths": {
            "@client/*": [
                "client/*",
            ],
            "@suir/*": [ // notice the `/*` at the end
                "../node_modules/semantic-ui-react/dist/commonjs/*", // notice the `/*`
            ],
        },
        // …
    },
    "include": [
        "./src/client/**/*",
    ],
}

Solution 2 - Typescript

As mentioned in the comments by Emily Zhai, this can sometimes just require a language server restart.

In VSCode, you can press Cmd/Ctrl + Shift + P and search for Typescript: Restart TS Server.

After restarting, everything started working for me.

Solution 3 - Typescript

I did also struggle with .tsconfig not recognizing my aliases (while in another project that supposed to have the save config it worked perfectly).

As it turned out, it was a rookie mistake: I put the paths prop to the end of the JSON object, but it has to be a nested property of the compilerOptions part:

// This does't work ❌
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
     //...
    "baseUrl": ".",
  },
  "include": ["next-env.d.ts", "twin.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"],
  "paths": {
      "@components/*": ["components/*"],
      "@lib/*": ["lib/*"]
    }
}
// This should work ✅
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
     //...
    "baseUrl": ".",
    "paths": {
      "@components/*": ["components/*"],
      "@lib/*": ["lib/*"]
    }
  },
  "include": ["next-env.d.ts", "twin.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"],
}

Solution 4 - Typescript

This might help someone - if you use tsc or a tool to compile your TS code to a separate folder such as dist, tsconfig-paths register does NOT work out the box. I have a tsconfig.json like this:

{
	"compilerOptions": {
		"target": "es5",
		"module": "commonjs",
		"lib": ["dom", "esnext"],
		"baseUrl": ".",
		"jsx": "react",
		"removeComments": true,
		"sourceMap": true,
		"outDir": "dist"
		"rootDir": ".",
		"paths": {
			"shared/*": ["./shared/*"],
		}
	},
	"include": ["./client/**/*", "./server/**/*"]
}

You can see that a path such as shared/someFolder/someScript will resolve correctly to the shared folder in my project, which is a load cleaner than lots of relative ../../../../ paths.

However, this was throwing me the error:

➜  game git:(game-dev) ✗ node --inspect -r tsconfig-paths/register dist/server/runProd.js
Debugger listening on ws://127.0.0.1:9229/f69956aa-d8d6-4f39-8be1-9c3e8383d4be
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
internal/modules/cjs/loader.js:584
    throw err;
    ^

Error: Cannot find module 'shared/types/UserTypes'

I did a bit of digging and found that the tryPaths array produced by tsconfig-paths has absolute URLs relative to the project/cwd base, rather than the build dist folder.

inspect screengrab

This seems obvious in retrospect. There doesn't seem to be an obvious way to handle this with the library, so I have solved this by copying the tsconfig.json into the dist folder and running node -r tsconfig-paths/register main.js.

Solution 5 - Typescript

Out of the box, it doesn't work with tsc or ts-node. But with some packages (tsc-alias & module-alias), it works. No babel or webpack setup are required.

// tsconfig.json

{
  "compilerOptions": {
    ...
    "baseUrl": "./src",
    "paths": {
      "@common/*": ["common/*"],
      "@services/*": ["services/*"],
    },
    ...
  },
}

Working with TSC

Add tsc-alias (https://www.npmjs.com/package/tsc-alias) as dev dependency

yarn add --dev tsc-alias

And add it to your build command

"build": "tsc && tsc-alias",

Working with TS-NODE

Add module-alias (https://www.npmjs.com/package/module-alias) dependency

yarn add module-alias

Create a file referencing all aliases

// src/paths.ts

import 'module-alias/register';
import { addAliases } from 'module-alias';

addAliases({
  '@common': `${__dirname}/common`,
  '@services': `${__dirname}/services`,
});

And import it in your entry script as first import

// src/server.ts

import './paths';
import express, { Request, Response, NextFunction } from 'express';
...

const app = express();
...
app.listen(port, onListen(port));

Solution 6 - Typescript

Like, pkestikar said, tsconfig-paths-webpack-plugin can help with that. Save it on devDependencies with yarn add --dev tsconfig-paths-webpack-plugin , add the following configuration on next.config.js

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

module.exports = {
  resolve: {
    plugins: [new TsconfigPathsPlugin({ configFile: "./tsconfig.json" })]
  }
}

My paths started to work with that. Here's my tsconfig.json

"compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@components/*": ["components/*"]
    },
}

And here is the import of a component.

import { Button } from '@/components/Button/Button'

It works with just import { Button } from 'components/Button/Button' as well.

Solution 7 - Typescript

Even if the base url is set check if it's on the default value "./" then should be changed to "src", only that way worked for me.

Solution 8 - Typescript

If someone still has this issue even after doing everything mentioned. Try close down VS code and reopen again, that worked for me 2 hours after looking around..

Solution 9 - Typescript

If you are using Webpack with ts-loader and it's still not working after trying all of the answers above, you might need to use a plugin in the resolve section of your Webpack config file - tsconfig-paths-webpack-plugin; so it follows the paths you've put in in your tsconfig.json file while compiling.

Source - https://github.com/TypeStrong/ts-loader#baseurl--paths-module-resolution

Solution 10 - Typescript

For myself, after much trial and error the solution was simple. Remove this line from my tsconfig and it worked.

"extends": [
    "plugin:import/recommended",
]

and

"rules": {
    "import/no-unresolved": "error",,
}

Solution 11 - Typescript

I had to use babel to compile the code

npm i -D @babel/cli @babel/core @babel/node @babel/preset-env @babel/preset-typescript babel-plugin-module-resolver

Then on the build command

"build": "babel src --extensions \".js,.ts\" --out-dir dist --copy-files --no-copy-ignored"

And the babel.config.js

module.exports = {
presets: [
    [
        '@babel/preset-env',
        {
            targets: {
                node: 'current'
            }
        }
    ],
    '@babel/preset-typescript'
],
plugins: [
    ['module-resolver', {
        alias: {
            '@config': './src/config',
            '@modules': './src/modules',
            '@shared': './src/shared'
        }
    }]
],
ignore: [
    '**/*.spec.ts'
]

}

Solution 12 - Typescript

In my case the issue was that I was adding path to the wrong file. If you are working on a big project where you are not sure of it's configurations, chances are that the config file be extended by other files. In my project there was another file called tsconfig.app.json, notice the extend attribute in the very first row:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "paths": {
      "@angular/*": [
        "../node_modules/@angular/*",
      ],
      "@app/*": ["app/*"]
    }
}

Solution 13 - Typescript

After some trial and error, I got to know that, it works differently than we think.

//tsconfig.json
"baseUrl": ".",
"paths": {
  "@components/": ["src/components/"],
}

//SomeCompomonent.tsx
import { Button } from "@components/" // will work
import Button from "@components/Button" // will not work

to make the second import line work you need to put *

//tsconfig.json
"baseUrl": ".",
"paths": {
  "@components/*": ["src/components/*"],
}

//SomeCompomonent.tsx
import { Button } from "@components/" // will not work
import Button from "@components/Button" // will work

To make both work

//tsconfig.json
"baseUrl": ".",
"paths": {
  "@components/": ["src/components/"],
  "@components/*": ["src/components/*"],
}

//SomeCompomonent.tsx
import { Button } from "@components/" // will work
import Button from "@components/Button" // will work

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJakob JingleheimerView Question on Stackoverflow
Solution 1 - TypescriptJakob JingleheimerView Answer on Stackoverflow
Solution 2 - TypescriptMitch TalmadgeView Answer on Stackoverflow
Solution 3 - TypescriptHynekSView Answer on Stackoverflow
Solution 4 - TypescriptHughethView Answer on Stackoverflow
Solution 5 - TypescriptCam CHNView Answer on Stackoverflow
Solution 6 - TypescriptMatheus BologniniView Answer on Stackoverflow
Solution 7 - TypescriptPoly HamzaView Answer on Stackoverflow
Solution 8 - TypescriptTobbin2View Answer on Stackoverflow
Solution 9 - TypescriptpkestikarView Answer on Stackoverflow
Solution 10 - TypescriptJamie HutberView Answer on Stackoverflow
Solution 11 - TypescriptVyTor BrBView Answer on Stackoverflow
Solution 12 - TypescriptNaser NikzadView Answer on Stackoverflow
Solution 13 - TypescriptDhiraj ArunView Answer on Stackoverflow