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.jsmodule.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.