'How do I configure absolute paths for imports in TypeScript based React Native apps?

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

It is important that the configuration also supports Jest unit tests.

I created the app using npx react-native init MyTestApp --template typescript

React Native version: 0.60.5

What is the exact configuration I would need to achieve this?



Solution 1:[1]

Requirement

// Meh
import config from '../../../../../../../config';

// Awesome!
import config from '@cuteapp/config';

How To

  1. Add this babel plugin package
yarn add --dev babel-plugin-module-resolver
  1. My 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'
  ]
};
  1. My 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"]
}
  1. Restart the IDE.
  2. That's it.

Solution 2:[2]

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:

  1. Install babel-plugin-module-resolver using npm or yarn.

    npm i babel-plugin-module-resolver --save-dev
    
    # Or (If you're using yarn):
    
    yarn add --dev babel-plugin-module-resolver
    
  2. tsconfig.json: Add "baseUrl": "." to compilerOptions

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

Solution 3:[3]

If you do not want to use the babel plugin

  1. create a new package.json file inside the src folder with the following. (change myapp to whatever you want to, it can even be src.)
{
  "name": "myapp"
}
  1. update your tsconfig.json file
{
  "compilerOptions": {
     ...
     "baseUrl": "./",
     "paths": {
       "myapp/*": ["src/*"]
     }
     ...
  }
}
  1. In your.tsx file
import { MyThing } from 'myapp/MyThing';

Solution 4:[4]

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.

Solution 5:[5]

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";

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mohd Ilyas
Solution 2 0xInfection
Solution 3 Olcay ErtaÅŸ
Solution 4 Andrei Konstantinov
Solution 5 Nick