Why are these tsconfig paths not working?
Asked Answered
Y

23

124

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
Yaw answered 4/6, 2018 at 10:58 Comment(1)
Just wanted to add to this. For me, paths stop working when i use the files property in tsconfig.json. Any solution for this?Cretaceous
Y
125

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/**/*",
    ],
}
Yaw answered 16/6, 2018 at 14:43 Comment(9)
For anyone else still having the problem even though having /* make sure your baseUrl is set, as I just spent hours trying to fix this.Stickney
please edit this post and add what @Stickney said about the baseUrl. Thank you!Flow
In case anyone is using VSCode and having trouble getting the /* solution to work. Try Cmd+Shift+P > Typescript: Restart TS Server.Dewie
@Stickney still not working with base url as "./'Mcfadden
thanks @EmilyZhai it did the trick for me!Scanties
it worked! but still got absolutely no idea whyUnipersonal
this worked for me! pretty confused why so many examples online omit the /*. maybe they're all using webpack?Huckleberry
@Stickney 'As of TypeScript 4.1, baseUrl is no longer required to be set when using paths’ typescriptlang.org/tsconfig#baseUrlLetti
per @HynekS answer on this question, its best to have baseUrl as "." everything is relative to the project folder not src folder (as per this answer)Rumania
N
83

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.

Nonunionism answered 25/12, 2020 at 8:12 Comment(5)
Note that you might need to be in a .ts file for that option to appear. (I had to be focused on a .ts file.)Habilitate
Restart worked for me using Webstorm - thanks!Wristlet
Thank you so so much!! Without this answer I don't know how much more time I would had spent surfing the web to solve this!Shandashandee
@Shandashandee :) It has bitten me multiple times. So many hours wasted on what was just a simple restartNonunionism
Typescript: Restart TS Server <- this should be in every tutorial that ever mentions adjusting baseUrl or paths..Partridge
V
78

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"],
}
Vibrator answered 12/4, 2021 at 5:28 Comment(11)
Man! you are a lifesaver! I literally spent 2 days just on this small mistake!Demona
Glad I could help. I think it's quite counter-intuitive, considering "include" and "exclude" (which are also relative paths) being placed in the object root.Vibrator
Omg, I was looking for this for 3 hours already, I was going nutsMojgan
This in combination with the /* magic at the end for BOTH the ALIAS ( @components /* )itself and the path made things work, except images - for those I had to add custom typing files as described here - https://mcmap.net/q/182093/-ts2307-cannot-find-module-39-images-logo-png-39 basically you create a special file in typings/custom/import-yourextension.d.ts in your project rootRaama
Thank you, worked for me! Luckily I found this SO article rather quickly. Interesting: This worked before with Angular 9. With updating to Angular 12, I got Error: Module not found: Error: Can't resolve .... Now it's ok again !Psychopath
Than you, worked for me.Eroticism
@Vibrator THANK YOU SO MUCH!!! If you had a coffee button I'd gladly buy you one because MAN! lolPutman
@Putman Unfortunately, I dont' have one yet.. :) Glad I could help.Vibrator
@Vibrator paths supposed to be in compilerOptions. How does the first code even get allowed by the IDE?Dingman
Spent a whole day just to see this the next day, damn, thanks man!Diazo
I received the same error but was a different issue. my tsconfig.json within the "include": [... "../*.tsx"] was not included. Once I added that, the baseUrl as "." and the paths as: {"@/utils/*": ["src/utils/*"],} it worked. Thanks to everyone who took the time to help me figure this out!Lvov
B
45

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));
Bleeding answered 23/4, 2021 at 9:28 Comment(5)
just to mention, for module-alias might be required to install types also: npm i --save-dev @types/module-aliasLeith
Wow! I though tsc would work out of the box! Thank you for clarifingFeckless
You can also add NODE_PATH=outDir before node startDepend
Thanks so much. Was about to pull my hair out.Rattrap
Thank you! This answer needs to get bumped higher!Thisbe
A
34

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.

Ameeameer answered 1/11, 2019 at 21:23 Comment(1)
Great explanation! Relevant Github issue: github.com/dividab/tsconfig-paths/issues/75Synoptic
R
11

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
Rhamnaceous answered 16/3, 2022 at 4:42 Comment(2)
Thankssss! this worked for me 'cause I use named imports :DDreamland
This helped out big time!!! thanks!Colb
A
9

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.

Acred answered 22/1, 2021 at 15:7 Comment(0)
B
8

If you are using Vite, you should install vite-tsconfig-paths.

npm i vite-tsconfig-paths --save-dev

Then, inject vite-tsconfig-paths using the vite.config.ts module

import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths()],
})

You may need to restart Vite and/or your TS server after making these changes.

Banish answered 30/6, 2022 at 18:8 Comment(2)
if this is not working check https://mcmap.net/q/182094/-ts-config-nested-alias-for-absolute-path-not-working. v4.0.0 have a bug. v4.0.1 fix it. Install with npm install vite-tsconfig-paths@latestVisually
Of all the solutions above, this is the one that worked for me with Vite.Polyptych
G
8

While trying to make tsconfig work, the following command proved very helpful:

npx tsc --showConfig

This will output some json with the files field showing the actual recognized files by your configuration.

Georgettageorgette answered 1/2, 2023 at 15:56 Comment(1)
What am I meant to see here if paths are working?Ruscio
C
4

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.

Cloudless answered 23/11, 2020 at 13:15 Comment(1)
Strange, but it works. I can confirm that. This advice saved me a lot of time.Vulgarian
S
4

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..

Schreck answered 12/9, 2021 at 1:10 Comment(1)
I had it working before, and numerous reloads didn't work. Complete close & reopen did!Quotable
P
2

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

Palembang answered 8/1, 2021 at 17:36 Comment(0)
G
1

Try add in tsConfig.json the follow property inside CompileOptions:

"baseUrl": "."

In my case working.

Goto answered 18/7, 2022 at 20:19 Comment(0)
D
1

Check your workspace

Check how you have opened your workspace in VScode.

In my case, I have this structure:

├── my-proyect
│   ├── client* (this is my react folder)
│   └── server

To make it work, I have o open the client folder. If I open the whole project it doesn't work.

Other things to check:

  1. tsconfig.json should be something like this
{
  "compilerOptions": {
   ...
    "baseUrl": "./src",
    "paths": {
      "~/*": ["./*"],
    }
  },
}
  1. vite.config.ts should be something like this (if you use vite)
import react from '@vitejs/plugin-react'
import path from 'path'
import { defineConfig } from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '~': path.resolve(__dirname, 'src'),
    },
  },
})

Restart TS Server.

In VSCode, you can press **Cmd/Ctrl + Shift + P** and search for Typescript: 
Duran answered 25/5, 2023 at 21:49 Comment(1)
Thanks! That was the solution for me 👍Wessling
S
1

In my case, even though I set baseUrl in the parent config, I had to set baseUrl again in the derived config to make VSCode happy and successfully resolve the configured paths enter image description here

Sidle answered 29/11, 2023 at 10:1 Comment(0)
C
0

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'
]

}

Crossroad answered 26/4, 2021 at 17:47 Comment(0)
D
0

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/*"]
    }
}
Dekaliter answered 4/12, 2021 at 7:34 Comment(0)
C
0

I will recommend, do not change tsconfig.json rather create tconfig.app.json and add following content If already exists then simply add paths, you can reuse your shortPath

Note: its json file so check comma (,) and don't miss or keep extras like in *.ts files


{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [],
    "paths": {
      "@app/*": ["src/app/*"],
      "@chat/*": ["@app/chat/*"],
      "@shared/*": ["@app/shared/*"],
      "@auth/*": ["@app/auth/*"]
    }
  },
  "files": [
    "src/main.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}
Confessor answered 14/1, 2023 at 21:16 Comment(0)
W
0

On top of Emily Zhai's comment, if someone wants to Restart TypeScript/ESLint Servers Automatically when configs changed on VS Code, my extension may help

Auto Restart TypeScript / ESLint Servers - Visual Studio Marketplace

Wyckoff answered 3/2, 2023 at 15:21 Comment(0)
B
0

for parcel with react add compilerOptions.paths and add parcel-resolver-tspaths to resolvers for .parcelrc(create if not present) file. or checkout Offical: https://parceljs.org/plugin-browser/?type=%22resolver%22&page=0&filter=%22resolver-path%22&includeOfficial=true

npm install --save-dev parcel-resolver-tspaths

package.json

{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"],
      "@utils/*": ["./src/utils/*"]
    },
  }
  ...
}

.parcelrc

{
  "extends": "@parcel/config-default",
  "resolvers": [
    "...",
    "parcel-resolver-tspaths"
  ],
  ...
}
Babbage answered 12/7, 2023 at 3:33 Comment(0)
O
0

If you have Javascript files, also check that in your tsconfig.json you have

 "allowJs": true

otherwise TypeScript will ignore .js and .jsx files imports

Oarfish answered 10/9, 2023 at 8:44 Comment(0)
R
-1

Make sure the path provided is correct. It will throw error "module and its decrations not found".

Rorqual answered 23/8, 2022 at 4:54 Comment(0)
N
-4

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",,
}
Nepotism answered 11/10, 2021 at 14:31 Comment(1)
This is not a solution and just removes the error. If the project is compiling without errors and eslint is still showing an error, then there is a misconfiguration in the eslint config.Souterrain

© 2022 - 2024 — McMap. All rights reserved.