CDK(TypeScript)のimport文で絶対パスを使用する

tsconfig.json で baseUrl を設定し、cdk.json で tsconfig-paths を使うようにします。
2022.02.17

TL;DR

  • tsconfig.json ファイルで baseUrl を設定します。
  • tsconfig-paths モジュールを導入します。
  • cdk.json ファイルを編集して ts-node に tsconfig-paths を適用します。

tsconfig.json ファイル

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "lib": ["es2018"],
    "baseUrl": "./", // プロジェクトルート(tsconfig.jsonを配置しているディレクトリ)からの絶対パスによる import を可能する
...
}

tsconfig-paths モジュールのインストール

$ npm install --save-dev tsconfig-paths

編集前後の cdk.json ファイルの差分:-r tsconfig-paths/register を追加

 {
-  "app": "npx ts-node --prefer-ts-exts bin/cdk-workshop.ts"
+  "app": "npx ts-node -r tsconfig-paths/register --prefer-ts-exts bin/cdk-workshop.ts"
 }

やりたいこと

TypeScript の CDK スクリプトにおいて、絶対パス(正確には、「リポジトリルート」のような特定ディレクトリからの相対パス)の import 文を書きたいです。 (深くネストしたファイルの import 文を簡潔に書きたいです)

import { SomeClass } from '../../../resource/SomeClass';

↓↓↓

import { SomeClass } from 'lib/resource/SomeClass';

問題は CDK コマンド実行時のエラー

「TypeScript」「import」「絶対パス」のキーワードでググると、tsconfig.json ファイルに baseUrl を設定すればよい、という情報はすぐに見つかります。

baseUrl の設定を試してみると、たしかにエディタ(VSCode)上ではコンパイルエラーは発生していないので、正常に import 処理できているように見えます。 が、CDK コマンドを実行すると下記のようなエラーが発生します。

Require stack:
- /SomeDirectory/bin/somApp.ts
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/SomeDirectory/bin/somApp.ts:4:1)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Module.m._compile (/SomeDirectory/node_modules/ts-node/src/index.ts:1056:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Object.require.extensions.<computed> [as .ts] (/SomeDirectory/node_modules/ts-node/src/index.ts:1059:12)
    at Module.load (node:internal/modules/cjs/loader:981:32)
Subprocess exited with error 1

CDK コマンドは ts-node モジュールを使用してトランスパイルしている

stack trace を見ると、「ts-node」というモジュールが関係しているようです。 このモジュールを調べてみると、どうやら TypeScript のトランスパイル処理を行うようです。

なるほど、CDK コマンドを実行している時は特に意識していなかったのですが、たしかに明示的にトランスパイルの処理を実行していませんでした。 それは、CDK コマンドの裏で ts-node が処理してくれていたのだな、と。

CDK 処理はどこで ts-node を呼び出しているのか調べてみると、cdk.json ファイル内に「ts-node」という文字列が現れているので、ここで呼び出していると理解しました。

次に ts-node に絶対パスによる import 文を解釈させる方法をググってみると、tsconfig-paths を使うべし、という情報が見つかります。 そして、cdk.json ファイルを冒頭に記載した通り編集し、CDK コマンドを実行してみるとエラーが解消されました!