TypeScriptでimportを絶対パスの参照にする

TypeScript, Next.js
2022-01-19

TypeScriptでES Moduleをimportを絶対パスで参照するやり方です。

絶対パスでimport文を書くと以下のようになります。

import { Heading } from '../../../components/common/Typography';
import { UserTypes } from '../../../constants';

import { Heading } from '@/components/common/Typography';
import { UserTypes } from '@/constants';

そもそもなぜ絶対パスなのか?

メリットデメリットをまとめてみました。個人的にはおすすめではありますが、マストではないかもです。

メリット

  • import構文における、ドット地獄からの開放
    • (ルートからのパスを記述するので)importするファイルがどの位置にあるかわかりやすい
  • ファイルを移動させても、import文を変更する必要はない
  • import対象ファイルがルートから近くなるにつれでパスの長さは短くなる

デメリット

  • 通常、エディタの補完は相対パスなので、エディタ側でパスの補完をする場合はその設定が必要
    • VSCodeの場合は "typescript.preferences.importModuleSpecifier" で設定可
  • ファイル名、ディレクトリ名を変更した際、影響するファイルが増える
  • import対象のファイルが近くにある場合は、相対パスで表記するより長くなる場合がある

TypeScriptでの設定の仕方

Next.js(with TypeScript)で設定する場合、tsconfigのcompilerOptionsにimportするルート位置とパスの略称を追加します。

pathsには接頭辞となるシンボルを設定しています。今回は @/ を指定してますが、別のシンボルでも構いません。

逆にシンボルがない場合はライブラリやNode.jsのモジュールと区別がつかなくなるため、利用できません。(webpackを利用する場合は優先順位があってシンボルなしでもできたような気もしますが・・)

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    ...
  }
}

TypeScriptでの設定は以上になります。jestやstorybookを利用している場合は以下の追加の設定が必要です。

jestの設定

jestを実行する際にモジュールの@部分を変換します。

// jest.config.ts

export default {
  ...
  moduleNameMapper: {
    ...
    // importの@を解決
    '@/(.*)': '<rootDir>/src/$1'
  },
}

storybookの設定

storybookも同様にパスを解決するように設定します。

参考: https://github.com/storybookjs/storybook/issues/3916#issuecomment-871283551

// .storybook/main.js

const path = require('path');

module.exports = {
  ...
  webpackFinal: async config => {
    // importの@を解決
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../src')
    };

    return config;
  }
}
Written by Kyohei Tsukuda who lives and works in Tokyo 🇯🇵 , building useful things 🔧.