In order to avoid \'../../../../\' style relative imports in a TypeScript based React Native app, I would like to configure the app so that I can use absolute imports instea
// Meh
import config from '../../../../../../../config';
// Awesome!
import config from '@cuteapp/config';
yarn add --dev babel-plugin-module-resolver
babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
require.resolve('babel-plugin-module-resolver'),
{
cwd: 'babelrc',
extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'],
alias: {
'@cuteapp': './app'
}
}
],
'jest-hoist'
]
};
tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["es2015", "es2015.promise", "es2016.array.include", "dom"],
"strict": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@cuteapp/*": ["app/*/index", "app/*"]
},
"noEmit": true,
"resolveJsonModule": true,
"target": "esnext",
"types": ["jest"]
},
"exclude": ["node_modules", "babel.config.js", "metro.config.js"]
}
Summary:
The npm package babel-plugin-module-resolver
is needed, as well as some configuration in tsconfig.json
and babel.config.js
Step by step:
npm install babel-plugin-module-resolver
(or yarn add babel-plugin-module-resolver
)
tsconfig.json
: Add "baseUrl": "."
to compilerOptions
babel.config.js
: Add a key named plugins
with the following value:
[
[
'module-resolver',
{
extensions: [
'.js',
'.jsx',
'.ts',
'.tsx',
'.android.js',
'.android.tsx',
'.ios.js',
'.ios.tsx'
],
root: ['.']
}
]
]
Complete configuration:
tsconfig.json
:
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["es6"],
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"target": "esnext",
"baseUrl": "."
},
"exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"]
}
babel.config.js
:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
extensions: [
'.js',
'.jsx',
'.ts',
'.tsx',
'.android.js',
'.android.tsx',
'.ios.js',
'.ios.tsx'
],
root: ['.']
}
]
]
};
This is for a clean new project created using npx react-native init MyTestApp --template typescript
on React Native version 0.60.5
You can solve it using 5 simple steps withou eject:
Step 1: Adding react-app-rewired into your devDependencies
.
yarn add -D react-app-rewired
or npm intall react-app-rewired --save-dev
Step 2: After installation, you'll be able to change package.json
default ReactsJS scripts to:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
}
Step 3: Creates a new file called tsconfig.paths.json
on root path, with content like:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"services/*": ["./src/shared/services/*"],
"interfaces/*": ["./src/shared/interfaces/*"]
}
}
}
Tip 1: you can choose which path you want to use, like:
@services, @interface, @src, ~, @, etc
just by changing the keys inside "paths": {}
The same is applied to it's value: ["src/shared/services/"], ["src/shared/interfaces/"], ["src/*"]
, use the relative path here.
Step 4: Into tsconfig.json
, before "compilerOptions"
you need to extends the tsconfig.paths.json
you just created.
Like this:
{
"extends": "./tsconfig.paths.json",
...//rest of file infos compilerOptions, include... whatever
}
Step 5: Creates a new file config-overrides.js
, adding your alias and relative paths on it:
const path = require('path');
module.exports = function override(config) {
config.resolve = {
...config.resolve,
alias: {
...config.alias,
'services': path.resolve(__dirname, 'src/shared/services'),
'interfaces': path.resolve(__dirname, 'src/shared/interfaces')
},
};
return config;
};
Tip 2: If you're using eslint
, remember to have an .eslintignore
file and add config-overrides.js
within it.
Restart your IDE or text editor, in my case VSCode.
It's DONE!. Now just run yarn start
or npm run start
All of the other answers didn't work for me with a freshly created React Native + Typescript project.
What worked for me was setting both baseUrl
and paths
in tsconfig.json
:
{
"baseUrl": ".",
"paths": {
"NAME_IN_PACKAGE_JSON/*": ["./*"]
}
}
Replace NAME_IN_PACKAGE_JSON with your package.json
's name field.
E.g. if the name field is myapp
you can do:
import HomeScreen from "myapp/screens/HomeScreen";
For anyone who uses TypeScript and just wants to use import with absolute paths without aliases.
Assuming all of your code folders are inside of src
.
Insert "baseUrl": "src"
in compilerOptions
object inside tsconfig.json
.
Now you can use absolute paths in imports.