DEV Community

Matt Brailsford
Matt Brailsford

Posted on • Updated on

Simplifying Imports with TypeScript Path Aliases in Umbraco v14

I recently attended the online Umbraco Manchester meetup where Rick Butterfield talked about Generating a TypeScript OpenAPI client from Umbraco's Content Delivery API. One really useful tip he suggested was using typescript path aliases to simplify your import paths, but on implementing his suggestion there was one tiny piece of missing information I needed so I thought I'd write this blog post to give a complete picture for any Umbraco package devs building in v14 that are using the recommended tooling (TypeScript + Vite).

Why Use Path Aliases?

In large TypeScript projects, managing imports can become a tedious task. You might find yourself navigating through multiple directories to import a single module. This is where path aliases come into play. They allow you to create shortcuts for directories, simplifying your import statements and making your code cleaner and easier to manage.

Let's take a look at a before and after example.

Before

import { Order } from '../../models/order.model.ts';
import { OrderLine } from '../../models/order-line.model.ts';
import { SomeComponent } from '../../../core/components/some-component.element.ts';
Enter fullscreen mode Exit fullscreen mode

After

import { Order } from '@uc-models/order.model.ts';
import { OrderLine } from '@uc-models/order-line.model.ts';
import { SomeComponent } from '@uc-components/some-component.element.ts';
Enter fullscreen mode Exit fullscreen mode

Here, @uc-models and @uc-components are path aliases that map to the directories ./src/models and ./src/core/components respectively.

Setting Up Path Aliases in TypeScript

To set up path aliases in TypeScript, you need to modify your tsconfig.json file. Here's how you can do it:

{
  "compilerOptions": {
    ...
    "baseUrl": "./src",
    "paths": {
      "@uc-models/*": ["models/*"],
      "@uc-components/*": ["core/components/*"]
    },
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode

In the compilerOptions object, we set the baseUrl to ./src. This is the directory that our path aliases will be relative to. Then, in the paths object, we define our path aliases. Each key is a path alias, and the corresponding value is an array of paths that the alias should map to.

Integrating Path Aliases with Vite

If you're using Vite as your build tool (which we are at Umbraco), there's one more step you need to take. You need to define the same path aliases in your vite.config.ts file. Here's how you can do it:

export default defineConfig({
    ...
    resolve: {
        alias: {
            '@uc-models': path.resolve(__dirname, './src/models'),
            '@uc-components': path.resolve(__dirname, './src/core/components'),
        },
    },
    ...
});
Enter fullscreen mode Exit fullscreen mode

In the resolve object, we define an alias object. This object should have the same keys and values as the paths object in our tsconfig.json file.

UPDATE 2024-04-08
Thanks to Markus Johansson great suggestion in the comments, you can avoid having to duplicate your path declarations by installing vite-tsconfig-paths

npm install -D vite-tsconfig-paths
Enter fullscreen mode Exit fullscreen mode

Then updating your vite configuration accordingly.

import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths()],
})
Enter fullscreen mode Exit fullscreen mode

And that's it! You've now set up path aliases in your TypeScript project. This will make your import statements much cleaner and easier to manage. Happy coding!

Top comments (3)

Collapse
 
markusjoha profile image
Markus Johansson

Great article Matt! Thanks for sharing! Did you know about this vite plugin? npmjs.com/package/vite-tsconfig-paths It will basically take care of the 2nd step, so no need to duplicate the aliases in vite.config.

Collapse
 
mattbrailsford profile image
Matt Brailsford

Oooooh, I didn't know about that. That's perfect!

Collapse
 
lanalecoder profile image
LanAleCoder

Thanks for your input, I was starting a new course and the old way of doing it wasn't working.