Skip to content

Fix: TypeScript Path Aliases Not Working (Cannot Find Module '@/...')

FixDevs ·

Quick Answer

How to fix TypeScript path aliases not resolving — tsconfig paths configured but imports still fail at runtime, in Jest, or after building with webpack, Vite, or ts-node.

The Error

You configure path aliases in tsconfig.json and TypeScript stops complaining, but the code fails at runtime or during bundling:

Error: Cannot find module '@/utils/helpers'
Require stack:
- /app/src/index.ts

Or in Jest:

Cannot find module '@/components/Button' from 'src/App.test.tsx'

Or the TypeScript compiler itself:

error TS2307: Cannot find module '@/api/client' or its corresponding type declarations.

The import works in the editor (no red squiggles), but fails when you actually run or build the code.

Why This Happens

tsconfig.json path aliases (compilerOptions.paths) are a TypeScript compiler feature only — they tell the TypeScript type checker how to resolve module paths. They do not affect the JavaScript runtime or bundler module resolution.

When you run the compiled JavaScript with Node.js, or bundle with webpack/Vite/esbuild, those tools have no knowledge of your tsconfig.json paths and cannot resolve the aliases. Each tool needs its own alias configuration:

  • Node.js (with ts-node or compiled JS): needs tsconfig-paths or module alias setup.
  • webpack: needs resolve.alias in webpack.config.js.
  • Vite: needs resolve.alias in vite.config.ts.
  • Jest: needs moduleNameMapper in jest.config.js.
  • esbuild / ESBuild-based tools: needs alias in the build config.

Fix 1: Configure the Bundler (webpack)

If you use webpack, add the alias to webpack.config.js:

// webpack.config.js
const path = require("path");

module.exports = {
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
      "@components": path.resolve(__dirname, "src/components"),
      "@utils": path.resolve(__dirname, "src/utils"),
      "@api": path.resolve(__dirname, "src/api"),
    },
    extensions: [".ts", ".tsx", ".js", ".jsx"],
  },
};

This must match your tsconfig.json paths:

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

Pro Tip: Keep tsconfig.json paths and webpack.config.js aliases in sync manually — or use the tsconfig-paths-webpack-plugin to read paths from tsconfig.json automatically:

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

module.exports = {
  resolve: {
    plugins: [new TsconfigPathsPlugin()],
  },
};

Fix 2: Configure Vite

Vite uses Rollup for bundling and needs alias configuration in vite.config.ts:

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
      "@components": path.resolve(__dirname, "./src/components"),
      "@utils": path.resolve(__dirname, "./src/utils"),
    },
  },
});

For TypeScript projects, also install @types/node so path and __dirname are recognized:

npm install -D @types/node

Use vite-tsconfig-paths to sync automatically:

npm install -D vite-tsconfig-paths
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  plugins: [react(), tsconfigPaths()],
  // No need to manually configure resolve.alias
});

vite-tsconfig-paths reads your tsconfig.json and configures Vite aliases automatically.

Fix 3: Configure Jest

Jest has its own module resolver that does not read webpack or Vite config. Add moduleNameMapper to jest.config.js:

// jest.config.js
module.exports = {
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
    "^@components/(.*)$": "<rootDir>/src/components/$1",
    "^@utils/(.*)$": "<rootDir>/src/utils/$1",
    "^@api/(.*)$": "<rootDir>/src/api/$1",
  },
  // Other Jest config...
};

The regex pattern ^@/(.*)$ matches imports starting with @/ and maps them to the src/ directory. The $1 captures the rest of the path.

Or use jest-module-name-mapper to generate from tsconfig:

npm install -D jest-module-name-mapper
// jest.config.js
const { pathsToModuleNameMapper } = require("ts-jest");
const { compilerOptions } = require("./tsconfig.json");

module.exports = {
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
    prefix: "<rootDir>/",
  }),
};

ts-jest includes a helper that converts tsconfig.json paths to Jest’s moduleNameMapper format.

Fix 4: Fix ts-node and Node.js Runtime

When running TypeScript directly with ts-node or running compiled JavaScript with Node.js, path aliases are not resolved at runtime.

For ts-node — use tsconfig-paths:

npm install -D tsconfig-paths
# Run with ts-node and tsconfig-paths
ts-node -r tsconfig-paths/register src/index.ts

# Or add to package.json scripts
{
  "scripts": {
    "dev": "ts-node -r tsconfig-paths/register src/index.ts",
    "dev:watch": "ts-node-dev -r tsconfig-paths/register src/index.ts"
  }
}

Or configure in tsconfig.json via ts-node section:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "ts-node": {
    "require": ["tsconfig-paths/register"]
  }
}

For compiled JavaScript — use module-alias:

After compiling TypeScript to JavaScript, the aliases are still in the output. Use module-alias to resolve them at runtime:

npm install module-alias
// package.json
{
  "_moduleAliases": {
    "@": "dist/src",
    "@components": "dist/src/components",
    "@utils": "dist/src/utils"
  }
}
// At the top of your entry file (dist/src/index.js)
require("module-alias/register");

Fix 5: Fix the tsconfig.json baseUrl Requirement

paths in tsconfig.json requires baseUrl to be set. Without it, TypeScript ignores the paths configuration:

Broken — missing baseUrl:

{
  "compilerOptions": {
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

Fixed — add baseUrl:

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

baseUrl: "." sets the base directory for resolving non-relative module names to the directory containing tsconfig.json. The paths values are relative to baseUrl.

Common Mistake: Setting baseUrl: "src" and paths like "@/*": ["*"]. While this works for TypeScript, the actual filesystem paths differ from what bundlers expect. Use baseUrl: "." and explicit src/ prefixes in paths for clarity.

Fix 6: Fix Multiple tsconfig Files

Projects often have multiple tsconfig files (e.g., tsconfig.json, tsconfig.app.json, tsconfig.node.json). Make sure the paths are in the right config:

// tsconfig.json — base config
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

// tsconfig.app.json — extends base
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist"
  },
  "include": ["src"]
}

If your bundler references tsconfig.app.json but paths are only in tsconfig.json, they are inherited via extends. Verify with:

# Check what TypeScript resolves for a specific file
npx tsc --traceResolution 2>&1 | grep "@/utils"

Still Not Working?

Restart the TypeScript language server. In VS Code, run TypeScript: Restart TS Server from the Command Palette after changing tsconfig.json. The editor caches type information and may show stale errors.

Check for rootDir conflicts. If compilerOptions.rootDir is set to src/, paths like "@/*": ["src/*"] may not resolve correctly because src/ is already the root. Try "@/*": ["./*"] instead.

Check for case sensitivity. On macOS (case-insensitive filesystem), @/Utils/helpers and @/utils/helpers both work locally but fail on Linux servers. Use consistent casing throughout.

Check the moduleResolution setting. TypeScript 5.0+ with "moduleResolution": "bundler" handles paths differently. If upgrading TypeScript, check if this setting change affects resolution.

For module resolution errors in general (not alias-specific), see Fix: TypeScript Cannot Find Module. For Jest module errors, see Fix: Jest Cannot Find Module.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles