DEV Community

Benny Code
Benny Code

Posted on

Why I Don’t Like Path Aliases in TypeScript

If you’ve been around modern TypeScript projects, you’ve probably seen imports like this:

import { formatDate } from '@/utils/date'
Enter fullscreen mode Exit fullscreen mode

instead of this:

import { formatDate } from '../../utils/date'
Enter fullscreen mode Exit fullscreen mode

That little @/ is a path alias. It’s a shorthand you can configure in tsconfig.json so that you don’t need to count how many ../ levels you’re in when importing files.

What are path aliases?

In TypeScript, you enable them like this:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, instead of messy relative paths, you can just import from a clean root-based alias. Looks nice, right?

The problem they solve (and why I think it’s outdated)

Path aliases exist to save you from typing ../../../../ in imports. Fair enough but here’s the thing: modern IDEs already solved that problem.

In editors like VS Code, IntelliJ, and others, autocomplete instantly suggests the correct import path. When you move files around, the imports update automatically without you touching them. Even if the path happens to be long and messy, it doesn’t matter, because you never really type it by hand anyway.

So the “typing ../.. is painful” argument feels like a relic from 2015.

But don’t imports look messy?

Not really because we barely look at them. In editors like VS Code, imports collapse to a single line by default. Unless you’re adding a new one, or reviewing a diff, they’re out of sight, out of mind.

So whether the import says:

import { foo } from '../../../../utils/foo'
Enter fullscreen mode Exit fullscreen mode

or

import { foo } from '@/utils/foo'
Enter fullscreen mode Exit fullscreen mode

... doesn’t matter during normal coding.

When aliases are useful (for me)

I’ll admit that aliases are nice in one situation: copy-pasting code into docs, blog posts, or websites.

A code snippet with:

import { formatDate } from '@/utils/date'
Enter fullscreen mode Exit fullscreen mode

looks much friendlier to readers than:

import { formatDate } from '../../../../../utils/date'
Enter fullscreen mode Exit fullscreen mode

When someone doesn’t have the full context of your app’s folder structure, the alias makes the snippet cleaner.

The hidden danger of path aliases

Here’s the part alias fans don’t like to talk about:

Path aliases don’t actually work in compiled JavaScript.

TypeScript only knows about them because of tsconfig.json. When you compile your code, your output might still contain @/utils and Node.js or the browser has no idea what that means.

That means you now must use a bundler (Webpack, Rollup, tsup, Vite, etc.) or a tool like tsc-alias to rewrite paths at build time. If you forget, your published package or server build will break with:

Error: Cannot find module '@/utils'
Enter fullscreen mode Exit fullscreen mode

In other words, you introduced extra tooling complexity to solve a problem that wasn’t really a problem anymore.

Top comments (1)

Collapse
 
itsmearka profile image
Arka Chakraborty

If it doesn't really matter anyway, then I would say going the extra path to make it look readable is a bonus, also in a big team, path aliases so contribute a lot for clarity