Turborepo

TypeScript

TypeScript 在單一儲存庫中是一個出色的工具,它允許團隊安全地將類型添加到他們的 JavaScript 程式碼中。雖然設定過程有些複雜,但本指南將引導您了解大多數使用案例中 TypeScript 設定的重要部分。

本指南假設您正在使用最新版本的 TypeScript,並使用僅在這些版本中可用的某些功能。如果您無法使用這些版本的功能,您可能需要調整本頁上的指南。

共享 tsconfig.json

您希望在 TypeScript 設定中建立一致性,以便您的整個儲存庫可以使用出色的預設值,並且您的開發人員同事在工作區中編寫程式碼時可以知道會發生什麼。

TypeScript 的 tsconfig.json 設定 TypeScript 編譯器的組態,並具有一個 extends,您將使用它來共享整個工作區的組態。

本指南將使用 create-turbo 作為範例。

終端機
npx create-turbo@latest

使用基本 tsconfig 檔案

packages/typescript-config 內,您有幾個 json 檔案,它們代表您可能想要在不同套件中設定 TypeScript 的不同方式。base.json 檔案由工作區中的每個其他 tsconfig.json 延伸,如下所示

./packages/typescript-config/base.json
"compilerOptions": {
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "es2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "module": "NodeNext"
}
tsconfig 選項參考

建立套件的其餘部分

此套件中的其他 tsconfig 檔案使用 extends 鍵從基本設定開始,並針對特定類型的專案進行自訂,例如 Next.js (nextjs.json) 和 React 函式庫 (react-library.json)。

package.json 內,命名該套件,以便可以在工作區的其餘部分中引用它

packages/typescript-config/package.json
{
  "name": "@repo/typescript-config"
}

建構 TypeScript 套件

使用設定套件

首先,將 @repo/typescript-config 套件安裝到您的套件中

./apps/web/package.json
{
  "devDependencies": {
     "@repo/typescript-config": "*",
     "typescript": "latest",
  }
}

然後,從 @repo/typescript-config 套件延伸該套件的 tsconfig.json。在此範例中,web 套件是一個 Next.js 應用程式

./apps/web/tsconfig.json
{
  "extends": "@repo/typescript-config/nextjs.json",
  "compilerOptions": {
    "outDir": "dist"
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

建立套件的進入點

首先,請確保您的程式碼已使用 tsc 編譯,以便會有一個 dist 目錄。您將需要一個 build 指令碼以及一個 dev 指令碼

./packages/ui/package.json
{
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  }
}

然後,在 package.json 中設定套件的進入點,以便其他套件可以使用已編譯的程式碼

./packages/ui/package.json
{
  "exports": {
    "./button": {
      "types": "./src/button.ts"
      "default": "./dist/button.js",
    },
    "./input": {
      "types": "./src/input.ts"
      "default": "./dist/input.js",
    }
  }
}

以這種方式設定 exports 有幾個優點

  • 使用 types 欄位允許 tsserver 使用 src 中的程式碼作為程式碼類型的真實來源。您的編輯器將始終與您程式碼中的最新介面保持同步。
  • 您可以快速將新的進入點新增到您的套件,而無需建立危險的桶檔案
  • 您將在編輯器中收到跨套件邊界的匯入自動匯入建議。有關為什麼您可能不想萬用字元化進入點的更多資訊,請參閱限制章節

如果您要發布套件,則不能在 types 中使用對原始程式碼的參考,因為只有編譯後的程式碼會發布到 npm。您需要產生並參考宣告檔案和原始程式碼對應。

檢查程式碼的語法

若要使用 TypeScript 作為檢查工具,您可以使用 Turborepo 的快取和並行化來快速檢查整個工作區的類型。

首先,將 check-types 指令碼新增到您要檢查類型的任何套件

./apps/web/package.json
{
  "scripts": {
    "check-types": "tsc --noEmit"
  }
}

然後,在 turbo.json 中建立 check-types 任務。從設定任務指南,我們可以在使用傳輸節點時並行執行該任務,同時尊重其他套件的原始程式碼變更

./turbo.json
{
  "tasks": {
    "topo": {
      "dependsOn": ["^topo"]
    },
    "check-types": {
      "dependsOn": ["topo"]
    }
  }
}

然後,使用 turbo check-types 執行您的任務。

最佳實踐

使用 tsc 編譯您的套件

對於內部套件,我們建議您盡可能使用 tsc 編譯您的 TypeScript 程式庫。雖然您可以使用打包器,但這不是必要的,並且會為您的建置流程增加額外的複雜性。此外,打包程式庫可能會在程式碼到達應用程式的打包器之前就將其混淆,導致難以偵錯的問題。

啟用跨套件邊界的跳轉到定義功能

「跳轉到定義」是一種編輯器功能,可讓您透過點擊或熱鍵快速導覽至符號(如變數或函式)的原始宣告或定義。一旦正確設定 TypeScript,您就可以輕鬆地在內部套件之間導覽。

即時套件

只要您不使用進入點萬用字元,從即時套件匯出的內容將會自動將您帶到原始的 TypeScript 原始碼。跳轉到定義功能將會如預期般運作。

已編譯的套件

已編譯的套件匯出的內容,需要使用declarationdeclarationMap設定,才能使跳轉到定義功能正常運作。為套件啟用這兩個設定後,使用 tsc 編譯套件,並開啟輸出目錄以尋找宣告檔案和原始碼對應。

button.js
button.d.ts
button.d.ts.map

有了這兩個檔案,您的編輯器現在將導覽至原始碼。

使用 Node.js 子路徑匯入,而不是 TypeScript 編譯器的 paths

您可以使用TypeScript 編譯器的 paths 選項在您的套件中建立絕對匯入,但是當使用即時套件時,這些路徑可能會導致編譯失敗。自 TypeScript 5.4 起,您可以使用Node.js 子路徑匯入來獲得更穩健的解決方案。

即時套件

即時套件中,imports 必須指向套件中的原始碼,因為不會建立像 dist 這樣的建置輸出。

./packages/ui/package.json
{
  "imports": {
    "#*": "./src/*"
  }
}

已編譯的套件

已編譯的套件中,imports 指向套件的建置輸出。

./packages/ui/package.json
{
  "imports": {
    "#*": "./dist/*"
  }
}

您可能不需要專案根目錄中的 tsconfig.json 檔案

建構您的儲存庫指南中所述,您希望將工具中的每個套件都視為一個獨立的單元。這表示每個套件都應該有自己的 tsconfig.json 來使用,而不是參考專案根目錄中的 tsconfig.json。遵循這種做法將使 Turborepo 更容易快取您的類型檢查任務,從而簡化您的設定。

您可能需要在工作區根目錄中擁有 tsconfig.json 的唯一情況是,為不在套件中的 TypeScript 檔案設定組態。例如,如果您有一個使用 TypeScript 編寫的腳本需要在根目錄下執行,您可能需要該檔案的 tsconfig.json

然而,這種做法也不建議,因為工作區根目錄中的任何變更都會導致所有任務錯過快取。相反地,將這些腳本移動到儲存庫中的另一個目錄。

您可能不需要 TypeScript 專案參考

我們不建議使用 TypeScript 專案參考,因為它們會為您的工作區引入另一個設定點以及另一個快取層。這兩者都可能在您的儲存庫中造成問題,而且沒有什麼好處,因此我們建議在使用 Turborepo 時避免使用它們。

限制

您的編輯器不會使用套件的 TypeScript 版本

tsserver 無法在您的程式碼編輯器中為不同的套件使用不同的 TypeScript 版本。相反地,它會發現一個特定的版本並在所有地方使用該版本。

這可能會導致您的編輯器中顯示的 lint 錯誤與您執行 tsc 腳本來檢查類型時的錯誤之間存在差異。如果這對您來說是一個問題,請考慮將 TypeScript 相依性保持在相同的版本

套件進入點萬用字元

我們建議明確列出您套件的進入點 - 但是,對某些人來說,這感覺太冗長了。相反地,您可以使用萬用字元來捕捉進入點

./packages/ui/package.json
{
  "exports": {
    "./*": {
      "types": "./src/*.ts",
      "default": "./dist/*.js"
    }
  }
}

雖然這可以正常運作,但它會帶來一個缺點,即由於TypeScript 編譯器的效能原因,無法跨套件邊界自動匯入。根據您的用例,這種權衡可能值得或不值得。

小時

節省的總運算時間
開始使用
遠端快取 →

本頁內容