Using path aliases in React Native created with Expo and Typescript

Managing big apps have its own problems and one of them is managing imports. Typescript allows you to have path aliases which makes it easier to refer to modules. In this tutorial we will see how we can use path aliases in React Native app created using Expo and Typescript.
Using path aliases in React Native created with Expo and Typescript

Managing a big app always has its own set of problems. One problem that I've seen is managing the import paths to modules you are using. As your app becomes bigger, it makes it harder to manage these relative path. Especially if you have to move these files or folders around, refactoring can become harder.

How I like to manage a project is by creating folders with index.ts in it. I consider that folder to be its own package which exposes all its functionality through index.ts. This leads to a better interface of what a particular set of code provides and what are its internal details.

I have this very simple app that I created using the expo tool in React Native using Typescript. How the code was structured is that the main component refers to the counter component which is in this particular file in a separate folder /src/app-main/lib/index.ts so the import statement looks something like

import { Counter } from './src/app-main/lib/index.ts';

Typescript provider us a capability to add aliases for paths. If you open your tsconfig.json and then under compiler options you can add paths.

{
    "compilerOptions": {
        ...
        "paths": {
            "app-main": ["./src/app-main/lib/index.ts"],
            "app-counter": ["./src/app-counter/lib/index.ts"]
        }
    }
}

This tells Typescript how to resolve app-counter to that particular file.
This is not the complete picture. In case of React Native created using expo, Babel is the one that's actually doing the transformation, so we need to tell it about those aliases as well. Following are the changes that you have to make to babel.config.js

module.exports = function(api) {
    api.cache(true);
    return {
        ...
        plugins: [
            [
                'module-resolver',
                {
                    ...
                    alias: {
                        'app-main': './src/app-main/lib/index.ts',
                        'app-counter': './src/app-counter/lib/index.ts',
                    },
                },
            ],
        ],
    };
};

Now I can get rid of all that relative path and make the imports more cleaner e.g.

import { Counter } from 'app-counter';

Make sure you start expor using -c e.g. yarn start -c otherwise it might still use the cache and not able to resolve those new aliases.

This also make it super easy to refactor as you can change where the folder and files are placed and only need to update the aliases, rest should work fine.