Search code examples
typescriptyarnpkglernayarn-workspaces

Lerna, yarn, and Typescript: Cannot find module or its corresponding type declarations


I have a lerna + yarn workspaces monorepo, with independent versioning. I'm having trouble importing a package in its sibling.

I have two packages, one of which should depend on the other, as illustrated below:

(root)
  |--packages
       |--money
       |--money-standard-units
            |--{deps. on money}

Inside of money-standard-deps, I try to import an exported member of money but I'm unable to do so; I get the following message:

TS2307: Cannot find module 'money' or its corresponding type declarations.

I know this issue can be resolved by adding money to the paths array of money-standard-libs's tsconfig, but I want to depend on the built package as these will be published seperately. I want this to effectively work as-if it's two seperate repos.

I've created a demo repo.


Solution

  • You will need to configure your typescript project to generate type declaration *.d.ts files if it is going to be used as a dependency of another typescript project. To do this, you will need to set the compilerOptions.declaration property of your tsconfig to true. You can do this in your tsconfig-common.json file.

    For example (tsconfig-common.json):

    {
      ...
      "declaration": true
      ...
    }
    

    Additionally, in the same way you specify a main property in your package.json file to identify the entry file for your package you will also need to specify a types property to specify where your type declaration file is located. You need to do this for every package in your monorepo.

    For example (package.json):

    {
      "name": "@somescope/money",
      ...
      "main": "dist/index.js",
      "types": "dist/index.d.ts",
      ...
    }
    

    Also, I noticed that you do a default export in your monetary-unit module, but then do a named import for it in the uses-money module.

    You will need to change the monetary-unit module to use a named export on the class if you intend to refer to it using a named import.

    Example (monetary-unit.ts):

    // Remove the default keyword
    export class MonetaryUnit {
      constructor(
        readonly value: number,
        readonly name: string,
      ) {}
    }