TypeScript 「Cannot find module」が発生した時に確認すること

自分が書いたコードの中で、以下のように node_modules にインストールしたモジュールを import していました。

import clipboard from 'clipboardy'

これをtscでトランスパイルしたところ以下のようなエラーがでました。

$ npx tsc
src/main.ts:1:23 - error TS2792: Cannot find module 'clipboardy'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?

メッセージに書いてある通り、moduleResolution に node をセットすることで解消しました。

{
  "compilerOptions": {
    "lib": ["ES2021"],
    "module": "ES2020",
    "target": "ES2021",
    "strict": true,
    "moduleResolution": "node"
    
  }
}

TypeScriptのモジュール解決の方法は二つあります。

以下に記載されている通り、module に commonjs が指定されている場合は Node の動きになり、それ以外の場合は Classic になるようです。

There are two possible module resolution strategies: Node and Classic. You can use the moduleResolution option to specify the module resolution strategy. If not specified, the default is Node for --module commonjs, and Classic otherwise (including when module is set to amdsystemumdes2015esnext, etc.).

https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies

上記の tsconfig.json では “module": “ES2020" なので、Classicの動きになったようです。

そして、Classic の場合はモジュール解決時に node_modules 配下は見ません

もし、node_modules 配下のモジュールの import で Cannot find module となった場合は、moduleResolution: “node" を設定してみると良いです。

公式にもそのことが記載されています。

Note: node module resolution is the most-commonly used in the TypeScript community and is recommended for most projects. If you are having resolution problems with imports and exports in TypeScript, try setting moduleResolution: "node" to see if it fixes the issue.

https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies