Make typescript compile/lint from the other modules/packages in monorepo

Viewed 218

I am new to using monorepo with Typescript which has a react-native project and a common folder which contains the common files to be shared across projects and it is configured and works fine when the app is running.

I am facing problem with Typescript which shows error in the common files import statements where react-native components are imported and used. It says Cannot find module 'react-native' or its corresponding type declarations.ts(2307). So is there a way to make Typescript to look for the import into the react-native project (Mobile directory) node_modules?

Monorepo structure:

monorepo
    |
    |---Common
    |
    |---Mobile 

Common's tsconfig.json

{
"compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "jsx": "react-native",
    "lib": [
        "es2021"
    ],
    "moduleResolution": "node",
    "noEmit": false,
    "strict": true,
    "target": "esnext",
    "rootDir": "./",
    "outDir": "./dist",
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "baseUrl": ".",
},
}

Mobile's tsconfig.json

{
"compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "jsx": "react-native",
    "lib": [
        "es2021"
    ],
    "moduleResolution": "node",
    "noEmit": false,
    "strict": true,
    "target": "esnext",
    "baseUrl": ".",
    "paths": {
        "*": ["*", "../Common/*"]
    },
    "composite": true,
    "rootDir": "./",
    "outDir": "./dist",
    "declaration": true,
    "declarationMap": true,
},
"references": [{ "path": "../Common" }],
"exclude": [
    "node_modules",
    "babel.config.js",
    "metro.config.js",
    "jest.config.js"
]
}
1 Answers

This has to do with your package.json, not the tsconfig.json. You're looking for peerDependencies. In short, this is used for libraries to say, "any application depending on this library should also depend on XYZ, so use the version of XYZ in the application".

In your package.json for Common, you'll have something like:

"peerDependencies": {
  "react-native": "^0.68.2"
},
"devDependencies": {
  "react-native": "^0.68.2"
}

Note that you also want it in devDependencies because, while developing and running unit tests, there is no other application that imports the dependency.


Sidenote: in a monorepo, it's fine for them all to use the same version, as you'll probably update them all at the same time. If you were developing a library that's standalone, you typically want to use the lowest compatible version in peerDependencies. It makes the library easier to use for consuming applications. I'm not up to date on react-native's versions, but e.g. if you made a library for normal React that uses hooks (which were introduced in 16.8), you might have:

"peerDependencies": {
  "react": "^16.8.0 || ^17.0.0"
},
"devDependencies: {
  "react": "^17.0.2",
Related