Skip to main content

Command Palette

Search for a command to run...

Stop Wrestling with Relative Imports: Master Absolute Imports in React + TypeScript + Vite

Tired of seeing ../../../components/Button in your React imports? Absolute imports are your solution for cleaner, more maintainable code. Here's how t

Updated
3 min read
Stop Wrestling with Relative Imports: Master Absolute Imports in React + TypeScript + Vite

Why Absolute Imports Matter

The difference is immediately clear.

Before (Relative Imports):

TypeScript

import Button from '../../../components/ui/Button'
import { useAuth } from '../../../../hooks/useAuth'
import logo from '../../assets/images/logo.svg'

After (Absolute Imports):

TypeScript

import Button from '@/components/ui/Button'
import { useAuth } from '@/hooks/useAuth'
import logo from '@/assets/images/logo.svg'

Benefits

  • No more path confusion when moving files.

  • Cleaner, more readable import statements.

  • Easier refactoring and file organization.

  • Consistent imports across your entire project.


The Complete Setup

To get absolute imports working, you need to tell both TypeScript (for type checking and autocompletion) and Vite (your bundler) how to resolve these new paths.

1. tsconfig.json

This is the root TypeScript config. We just need to ensure it references our other TypeScript configurations. The key settings for path aliases will go in tsconfig.app.json.

JSON

{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}

2. tsconfig.app.json

This file configures TypeScript for your application code. Here we define the baseUrl and paths so that TypeScript understands the @ alias.

JSON

{
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2022",
    "useDefineForClassFields": true,
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Path Alias Configuration */
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

3. vite.config.ts

Finally, update your Vite configuration to resolve the path aliases during the build and development process.

TypeScript

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

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

Quick Setup Steps

  1. Install @types/node (required for using path and __dirname in vite.config.ts):

    Bash

     npm install -D @types/node
    
  2. Copy the configurations above into your respective files (tsconfig.json, tsconfig.app.json, and vite.config.ts).

  3. Restart your development server:

    Bash

     npm run dev
    
  4. Restart the TypeScript server in your IDE (In VS Code: Cmd + Shift + P → "TypeScript: Restart TS Server").


Usage Examples

Now you can use clean, absolute paths everywhere in your project.

TypeScript

// Components
import Header from '@/components/Header'
import Button from '@/components/ui/Button'

// Assets
import logo from '@/assets/logo.svg'
import heroImage from '@/assets/images/hero.jpg'

// Utils & Hooks
import { formatDate } from '@/utils/date'
import { useAuth } from '@/hooks/useAuth'

Key Configuration Details

  • "baseUrl": ".": This tells the TypeScript compiler that the root for path resolution is the project's root directory (where tsconfig.json is located).

  • "@/*": ["src/*"]: This is the path mapping. It tells TypeScript that any import starting with @/ should be mapped to the src/ directory.

  • path.resolve(__dirname, './src'): This is used in vite.config.ts to create a reliable, absolute file path to your src directory, ensuring Vite can find the files correctly regardless of the operating system.

Your imports are now cleaner, your code is more maintainable, and file reorganization is effortless. No more counting ../ levels!