iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Path Aliases

Path aliases let you import with a friendly prefix instead of deep relative paths. import { Button } from '@/components/Button' beats '../../../../components/Button' every time.

Setup

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

Use it

TS
import { Button } from '@components/Button';
import { db } from '@lib/db';
import type { User } from '@app/types';

Tell the runtime too

tsconfig only affects type checking. At runtime, your bundler (or Node) needs to know the aliases:

Vite — vite.config.ts
import { defineConfig } from 'vite';
import path from 'node:path';

export default defineConfig({
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src'),
        },
    },
});
Node — tsx + tsconfig-paths
# with tsx, native to most modern bundlers
# with ts-node:
ts-node --require tsconfig-paths/register src/index.ts

For testing — Vitest

Vitest picks up Vite's resolve aliases automatically — set them once, they work in tests too.

For Jest

jest.config.js
module.exports = {
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/src/$1',
    },
};

For monorepo workspaces

In workspaces, you often don't need paths at all — point package "main" at the entry file, install workspace deps, and TS resolves them through node_modules links.

Tip: Pick one convention per project. Mixing @/foo, ~/foo, and @app/foo across files is a maintenance trap. Most teams converge on a single @/ prefix.

Example

Example
// tsconfig.json
// {
//   "compilerOptions": {
//     "baseUrl": "./src",
//     "paths": {
//       "@app/*": ["./*"],
//       "@components/*": ["./components/*"]
//     }
//   }
// }
//
// import { Button } from '@components/Button';
console.log('Path aliases tidy up deep imports');
Try it Yourself »

Exercise

Setting that maps alias prefixes to filesystem paths.

compilerOptions. = { '@/*': ['./*'] }

Test yourself

Q1. Path aliases live in…
Q2. At runtime, aliases must also be configured in…
Q3. Most teams converge on the alias prefix…

Discussion

Loading…