跳至主要內容

Deno 中 TypeScript 概觀

Deno 的其中一個好處是,它在 Deno 中執行程式碼時,將 TypeScript 視為一級語言,就像 JavaScript 或 WebAssembly 一樣。這表示您可以在不安裝任何項目,只要安裝 Deno CLI,就能執行或匯入 TypeScript。

但等等,Deno 真正執行 TypeScript 嗎?您可能會問自己。嗯,這取決於您對執行這個詞的定義。有人可能會爭辯說,在瀏覽器中,您實際上也沒有執行 JavaScript。瀏覽器中的 JavaScript 引擎會將 JavaScript 轉譯成一系列的作業碼,然後在沙盒中執行這些作業碼。因此,它會將 JavaScript 轉譯成類似組譯語言的東西。甚至 WebAssembly 也會經歷類似的轉譯,因為 WebAssembly 與架構無關,而它需要轉譯成特定平台架構所需的特定機器作業碼,才能在該架構上執行。因此,當我們說 TypeScript 是 Deno 中的一級語言時,我們的意思是,我們試著讓使用者在撰寫和執行 TypeScript 時的體驗,能像 JavaScript 和 WebAssembly 一樣簡單直接。

在幕後,我們使用 Rust 和 JavaScript 的技術組合,來提供這種體驗。

它是如何運作的?

在高階層面上,Deno 會將 TypeScript(以及 TSX 和 JSX)轉換成 JavaScript。它透過結合我們內建到 Deno 中的 TypeScript 編譯器,以及一個名為 swc 的 Rust 函式庫來執行此操作。當程式碼經過類型檢查和轉換後,它會儲存在快取中,準備好供下次執行,而無需再次將其從原始碼轉換成 JavaScript。

您可以透過執行 deno info 來查看此快取位置

> deno info
DENO_DIR location: "/path/to/cache/deno"
Remote modules cache: "/path/to/cache/deno/deps"
TypeScript compiler cache: "/path/to/cache/deno/gen"

如果您要查看該快取,您會看到一個目錄結構,它模擬該來源目錄結構和個別的 .js.meta 檔案(也可能是 .map 檔案)。.js 檔案是轉換後的來源檔案,而 .meta 檔案包含我們想要快取的關於檔案的元資料,目前包含來源模組的雜湊,它有助於我們管理快取失效。您也可能會看到一個 .buildinfo 檔案,它是一個 TypeScript 編譯器增量建置資訊檔案,我們快取它以幫助加速類型檢查。

類型檢查

TypeScript 的主要優點之一是您可以讓程式碼更安全,因此語法上有效的 JavaScript 會變成 TypeScript,並會顯示關於「不安全」的警告。

您可以使用以下指令類型檢查您的程式碼(不執行它)

deno check module.ts
# or also type check remote modules and npm packages
deno check --all module.ts

類型檢查可能需要大量時間,特別是如果您正在處理一個您進行大量變更的程式碼庫。我們已嘗試最佳化類型檢查,但它仍然需要付出代價。因此,預設情況下,TypeScript 模組在執行之前不會進行類型檢查。

deno run module.ts

在使用上述指令時,Deno 只會在執行模組之前轉譯它,忽略任何潛在的類型相關問題。為了在執行發生之前執行模組的類型檢查,必須將 --check 參數與 deno run 一起使用

deno run --check module.ts
# or also type check remote modules and npm packages
deno run --check=all module.ts

雖然 tsc 在遇到診斷(類型檢查)問題時(預設情況下)仍會發出 JavaScript,但 Deno 目前將它們視為終端。在使用 --check 參數 deno run 一起使用時,與類型相關的診斷會阻止程式執行:它會在這些警告上暫停,並在執行程式碼之前結束程序。

為避免此情況,您需要解決問題、使用 // @ts-ignore// @ts-expect-error 實用程式,或略過所有類型檢查。

您可以在 這裡 瞭解更多關於類型檢查參數的資訊。

判斷檔案類型

由於 Deno 支援 JavaScript、TypeScript、JSX、TSX 模組,因此 Deno 必須決定如何處理這些類型的檔案。對於本機模組,Deno 完全根據副檔名做出此判斷。當本機檔案中沒有副檔名時,會假設它是 JavaScript。

對於遠端模組,會使用媒體類型 (mime-type) 來判斷模組類型,其中模組路徑用於協助影響檔案類型,當檔案類型不明確時。

例如,.d.ts 檔案和 .ts 檔案在 TypeScript 中具有不同的語意,並且在 Deno 中需要不同的處理方式。雖然我們預期將 .ts 檔案轉換為 JavaScript,但 .d.ts 檔案不包含「可執行」程式碼,而只是描述類型(通常是「純」JavaScript)。因此,當我們擷取遠端模組時,.ts..d.ts 檔案的媒體類型看起來相同。因此,我們會查看路徑,如果我們看到路徑以 .d.ts 結尾,我們會將其視為類型定義檔案,而不是「可執行」TypeScript。

支援的媒體類型

下列表格提供 Deno 在識別遠端模組檔案類型時所支援的媒體類型清單

媒體類型檔案處理方式
application/typescriptTypeScript(受路徑副檔名影響)
text/typescriptTypeScript(受路徑副檔名影響)
video/vnd.dlna.mpeg-ttsTypeScript(受路徑副檔名影響)
video/mp2tTypeScript(受路徑副檔名影響)
application/x-typescriptTypeScript(受路徑副檔名影響)
application/javascriptJavaScript(受路徑副檔名影響)
text/javascriptJavaScript(受路徑副檔名影響)
application/ecmascriptJavaScript(受路徑副檔名影響)
text/ecmascriptJavaScript(受路徑副檔名影響)
application/x-javascriptJavaScript(受路徑副檔名影響)
application/nodeJavaScript(受路徑副檔名影響)
text/jsxJSX
text/tsxTSX
text/plain嘗試判斷路徑副檔名,否則未知
application/octet-stream嘗試判斷路徑副檔名,否則未知

預設為嚴格

Deno 預設以嚴格模式類型檢查 TypeScript,而 TypeScript 核心團隊建議嚴格模式為合理的預設值。此模式通常會啟用 TypeScript 的功能,這些功能可能應該從一開始就存在,但隨著 TypeScript 持續演進,這將會對現有程式碼造成重大變更。

混合 JavaScript 和 TypeScript

預設情況下,Deno 不会類型檢查 JavaScript。這可以更改,並在 在 Deno 中設定 TypeScript 中進一步討論。Deno 在複雜情況下支援 JavaScript 匯入 TypeScript 和 TypeScript 匯入 JavaScript。

不過有一個重要的注意事項,在 TypeScript 進行類型檢查時,Deno 預設會「讀取」所有 JavaScript,才能評估它可能如何影響 TypeScript 類型。類型檢查器會盡可能找出匯入到 TypeScript 中的 JavaScript 類型,包括讀取任何 JSDoc 註解。詳細資訊會在 類型和類型宣告 區段中詳細說明。

類型解析

Deno 的核心設計原則之一是避免非標準模組解析,這也適用於類型解析。如果你想要使用有類型定義的 JavaScript(例如 .d.ts 檔案),你必須明確告知 Deno。如何完成此操作的詳細資訊會在 類型和類型宣告 區段中說明。