TypeScript path alias tsconfig

解析 TypeScript 宣告檔案中的路徑別名 - Resolve path alias in TypeScript declaration files

林承甫 Chengfu Lin 2022/03/04 09:07:48
4722

在使用  TypeScript 開發 library 或應用的過程中,會為了簡化、清楚 import 的路徑

從原本的相對路徑

import { MyClass } from '../../classes/my-class';

改為使用別名 (path alias)

定義在 tsconfig 檔案中,如:

{
    "compilerOptions": {
        "paths": {
            "@classes/*": ["classes/*"],
            "@interfaces/*": ["interfaces/*"],
            "@enums/*": ["enums/*"],
            "@types/*": ["types/*"],
            "@services/*": ["services/*"]
        }
    }
}

便可將 import 路徑調整為

import { MyClass } from '@classes/my-class';

 

在 compile 階段,就需要能產出,讓 JS / TS 在 import 時能夠正確找到對應的路徑方式

因此,這裡以使用  TypeScript 開發套件,透過 webpack 建置的使用為情境,介紹可能遇到的解析路徑的情況與解決方式。

 


 

Webpack - Resolve Alias

為了在 JS 檔案中能 import/require 使用,會透過 webpack config 的 resolve 區塊定義 alias [參考 webpack 官方文件]

或透過套件 tsconfig-paths-webpack-plugin  便可直接以  tsconfig.json 的設定為主

如:

module.exports = {
  ...
  resolve: {
    // `extensions` is required, if `allowJs` is set in tsconfig
        extensions: ['.ts', '.tsx', '.js'],
        plugins: [
            new TsconfigPathsPlugin({
                configFile: 'tsconfig.prod.json',
                extensions: ['.ts', '.js'],
            }),
        ],
  }
  ...
}
configFile 預設為 tsconfig.json


但是,僅僅以此設定 compile 並無法直接在 TypeScript 應用中使用

會在某個 .d.ts 中出現這樣的錯誤:
Cannot find module '@classes/my-class' or its corresponding type declarations


因此我們需要一個酷東西

TypeScript Transformer 

將產出的 .d.ts 檔案中 import 的路徑做轉換

使用的 transformer 是:typescript-transform-paths

 

而這個功能會需要使用 ttypescript (Tranformer TypeScript)

ttypescript 在 repository 上的說明 中描述,提供 typescript 在 compile 階段執行 transformer:

 

"Currently TypeScript doesn't support custom transformers in the tsconfig.json, but supports it programmatically.

And there is no way to compile your files using custom transformers using tsc command.

TTypescript (Transformer TypeScript) solves this problem by patching on the fly the compile module to use transformers from tsconfig.json."

 

因此,需要安裝他,並調整一下 tsconfig 與 webpack config,設定使用的  transformer (這裡就是 typescript-transform-paths)

參見 typescript-transform-paths 套件的設定說明:

{
    "compilerOptions": {
        // Note: To transform paths for both the output .js and .d.ts files, you need both of the below entries
        "plugins": [
          // Transform paths in output .js files
          { "transform": "typescript-transform-paths" },

          // Transform paths in output .d.ts files (Include this line if you output declarations files)
          { "transform": "typescript-transform-paths", "afterDeclarations": true }
        ]
    }
}

若 plugins 中兩個設定都有加上,則 webpack config 中  resolve 就不需要定義  alias 了

相對的,若 tsconfig 中  plugins 只使用

{ "transform": "typescript-transform-paths", "afterDeclarations": true }

則 webpack config 就需要處理 js 中使用的 alias

 

此外,webpack config 需要調整 typescript loader 使用的  compiler 為 ttypescript

module.exports = {
...
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: require.resolve('ts-loader'),
                exclude: /node_modules/,
                options: {
                    compiler: 'ttypescript',
                    configFile: 'tsconfig.prod.json',
                },
            },
        ],
    },
...
};

 

都調整好以後, compile 完成,可以查看 .d.ts 中 import 的路徑都有被替換

如此就能正常在  TypeScript 應用中使用了

 


 

References

1. "Resolve path alias in declaration files (d.ts)" - issue

2. ttypescript

3. typescript-transform-paths

林承甫 Chengfu Lin