So you've got a React Native app, you're using TypeScript, and you're being killing by long package imports. Let's fix that.
Take the project structure below - if I want to import CircleButton
in components from my StopWatch.tsx
in screens it's going to look like this:
import { CircleButton } from '../../components/buttons';
/Users/spencer/Dev/ClockApp
├── App.tsx
├── app.json
├── babel.config.js
├── package.json
├── src
| ├── components
| | ├── buttons
| | | ├── CircleButton.tsx
| | | └── index.tsx
| ├── index.tsx
| └── screens
| └── Clocks
| └── StopWatch.tsx
├── tsconfig.json
└── yarn.lock
Let's fix that so your import statement can look like
import { CircleButton } from 'components/buttons';
or better yet
import { CircleButton } from 'buttons';
To accomplish this you need to update two files.
TypeScript Path Alias
The first is tsconfig.json
. This is for TypeScript to understand the path alias.
First set your baseUrl
to .
, which represents the root of the directory. Every path in your tsconfig will be relative to that.
You then add your path alias' to the paths
object. I'm going to add one for the components directory (components/buttons
) and a direct one to the button exports (buttons
).
// tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
// Path alias config
"baseUrl": ".",
"paths": {
// This needs to be mirrored in babel.config.js
// Components is a directory with sub directories
"components/*": ["src/components/*"],
// We want to expose the exports of the buttons index file
"buttons": ["src/components/buttons/index"]
}
}
}
That will allow TypeScript to parse the following:
import { CircleButton } from "components/buttons"
import { CircleButton } from "buttons"
React Native Path Alias
Now we need to handle React Native path alias so the packager knows where to actually grab the files.
First install the babel-plugin-module-resolver
as a developer dependency
yarn add --dev babel-plugin-module-resolver
npm install babel-plugin-module-resolver --save-dev
Now we can update the babel.config.js
file to use the module-resolver
plugin and point to our directories.
// babel.config.js
module.exports = function (api) {
api.cache(true)
return {
presets: ["babel-preset-expo"],
plugins: [
[
"module-resolver",
{
alias: {
// This needs to be mirrored in tsconfig.json
components: "./src/components",
buttons: "./src/components/buttons",
},
},
],
],
}
}
And you're all set! Now you can shorten your imports, type less, ease refactoring, and make it easier to scan code.
Pro tip: Want to use absolute paths but don't want to add an alias for every directory? Add your root directory (such as src) to the alias config as well!
// tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
// Path alias config
"baseUrl": ".",
"paths": {
// This needs to be mirrored in babel.config.js
"components/*": ["src/components/*"],
"buttons": ["src/components/buttons/index"],
"src/*": ["src/*"]
}
}
}
// babel.config.js
module.exports = function (api) {
api.cache(true)
return {
presets: ["babel-preset-expo"],
plugins: [
[
"module-resolver",
{
alias: {
// This needs to be mirrored in tsconfig.json
components: "./src/components",
buttons: "./src/components/buttons",
src: "./src",
},
},
],
],
}
}
Now you can use imports like import { CircleButton } from "src/components/buttons"
as well.
Hope that helps!
Top comments (0)