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/typescript | TypeScript(受路徑副檔名影響) |
text/typescript | TypeScript(受路徑副檔名影響) |
video/vnd.dlna.mpeg-tts | TypeScript(受路徑副檔名影響) |
video/mp2t | TypeScript(受路徑副檔名影響) |
application/x-typescript | TypeScript(受路徑副檔名影響) |
application/javascript | JavaScript(受路徑副檔名影響) |
text/javascript | JavaScript(受路徑副檔名影響) |
application/ecmascript | JavaScript(受路徑副檔名影響) |
text/ecmascript | JavaScript(受路徑副檔名影響) |
application/x-javascript | JavaScript(受路徑副檔名影響) |
application/node | JavaScript(受路徑副檔名影響) |
text/jsx | JSX |
text/tsx | TSX |
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。如何完成此操作的詳細資訊會在 類型和類型宣告 區段中說明。