How to Use TSConfig Path Aliases to Improve Your Code

Cover for How to Use TSConfig Path Aliases to Improve Your Code

TSConfig path aliases are a powerful tool that can help you to improve the readability, maintainability, and error-proofing of your TypeScript code. This allows for easier to read clean code, and enables us to move files around without having to update import paths in every file.

This is a huge time saver.

What Are Path Aliases?

The goal is to replace the following import statements:

// relative import path
import MyComponent from "../../../components/MyComponent";

with these import statements:

// alias import path
import MyComponent from "@components/MyComponent";

We can do this with a tsconfig.json or jsconfig.json file. We will be using TypeScript in this post.

How To Setup Path Aliases

Adding Path Aliases To Your TSConfig File

We need to update our tsconfig.json file to enable aliases. We will add a paths and baseUrl property to the compilerOptions object. Each path is relative to the baseUrl.

This will tell TypeScript to replace the alias with the actual path when compiling the code.

{
	"compilerOptions": {
		"baseUrl": ".", // root of your "paths" below. Required if "paths" is defined
		"paths": {
			"@components/*": ["src/components/*"] // enables us to use @components/MyComponent
		}
	}
}

Using Path Aliases In Your Code

Now in all of your source files, you can import components like this:

// Without path aliases
import Hero from "../../../components/Hero";
import Footer from "../../../components/Footer";

// With path aliases
import Hero from "@components/Hero";
import Footer from "@components/Footer";

INFO

Frameworks like Astro and Next.js ship with built-in typescript support, although you may have to create the file tsconfig.json. Consult your framework’s documentation for more information.

Why Should I Do This?

Let’s say we have the following file structure:

.
└── src/
    ├── components/
    │   ├── Hero.tsx
    │   └── Footer.tsx
    └── pages/
        ├── index.tsx
        └── solutions.tsx

Annoying Relative Imports

If we want to import Hero.tsx and Footer.tsx into index.tsx and solutions.tsx, we would need the following import statements:

import Hero from "../components/Hero";
import Footer from "../components/Footer";

Refactoring Relative Imports

Now lets say we want to refactor. We now have multiple “solutions” and want to have each on their own page, and have them under a solutions directory. The file structure now looks like:

.
└── src/
    ├── components/
    │   ├── Hero.tsx
    │   └── Footer.tsx
    └── pages/
        ├── index.tsx
        └── solutions/
            ├── solution.tsx
            └── solution2.tsx

Now we have to update the import paths of solution.tsx:

import Hero from "../../components/Hero";
import Footer from "../../components/Footer";

You can see how this makes refactoring more of a chore. We have to update the import paths in every file that imports these components. This is a huge time sink and can lead to bugs if you forget to update the import paths.

Alias Imports Version

Alternatively, if from the start we were using aliases, we would not have to update any files using the components. This is far better for maintainability:

import Hero from "@components/Hero";
import Footer from "@components/Footer";

INFO

With this method, every file that needs to import these components will import them the same way. This makes it easier to move files around without having to update import paths.

Additional Paths

This can be extended to any number of path aliases. Some other potential ones you might use:

{
	"compilerOptions": {
		"baseUrl": ".",
		"paths": {
			"@config/*": ["src/data/*"],
			"@js/*": ["src/js/*"],
			"@layouts/*": ["src/layouts/*"],
			"@components/*": ["src/components/*"],
			"@assets/*": ["src/assets/*"]
		}
	}
}

TIP

When updating tsconfig.json, you may need to restart your editor for the changes to take effect.