· Jake Worth

Path aliases in TypeScript


You may have seen imports like this in an app:

app.tsx
import {Page} from '../../views/pages/Page';

Those ../../ paths get worse as the tree grows, and they break when you move files. Path aliases fix that by resolving from a fixed root (usually src/).

Here’s that same import with an aliased path:

app.tsx
import {Page} from '@/views/pages/Page';

The @ is a convention that represents a directory in your project, typically src/. Both TypeScript and your project’s build tooling need to know how to resolve it.

Implementing this is a bit different in every framework, so the best plan is to search “path aliases in <your framework>”. The TypeScript implementation will look something like this:

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

You can also alias general folders:

tsconfig.json
{
"compilerOptions": {
"paths": {
"@utils/*": ["./src/utils/*"]
}
}
}
app.tsx
import {formatDate} from '@utils/date';

Configurations like this are always a tradeoff. So, what are the arguments in favor of it?

First, path aliases autocomplete in text editors well. The import path doesn’t depend on the location of the importing file.

Second, path aliases let us move files around. When all imports are aliased, there’s less friction to moving a file, because every import works in any location.

I still use relative imports occasionally. One use case is an application with co-located stylesheets and tests. In a directory such as this:

$ ls src/components/
Login.tsx
Login.module.scss
Login.test.tsx

Relative imports are arguably a helpful convention for conveying familiarity:

Login.tsx
import {styles} from './Login.module.scss';
Login.test.tsx
import {Login} from './Login';
  • paths — TypeScript TSConfig Reference