有一天,我在一些處理樂觀更新的程式碼中遇到了一個錯誤,所以我向我的同事Filip尋求幫助。 TypeScript 精靈 Filip 提到satisfies
關鍵字將是我正在尋找的解決方案的一部分。
Satisfies
?那是什麼呀?為什麼我以前從未聽說過它?我的意思是,我已經使用 TypeScript 一段時間了,所以我很驚訝我自己並不了解它。
不久之後,我偶然發現了 @yacineMTB 的這條推文,他是X.com (又名 Twitter)的多產者和工程師:
就像,為什麼我不能只*執行*打字稿檔案?如果我需要初始化整個目錄和專案,那麼腳本語言有什麼意義呢?
我再次發現自己想知道為什麼我還不了解 TypeScript。為什麼你不能真正執行 TypeScript 檔案?腳本語言和編譯語言有什麼不同?
我突然意識到,我不太了解我幾乎每天使用的語言的一些基本知識,這些語言是我用來建立諸如Open SaaS (一個免費的開源 SaaS 入門工具)之類的東西的。
所以我決定退一步,對這些主題進行一些調查。在這篇文章中,我將與您分享我學到的一些最重要的事情。
您可能已經聽說過 TypeScript 是 JavaScript 的「超集」。這意味著它是 JavaScript 之上的一個附加層,在本例中,它允許您向 JavaScript 加入靜態類型。
這有點像 TypeScript 是 JavaScript 的進階版。或者,換句話說,如果 JavaScript 是 Tesla Model 3 的基礎模型,那麼 TypeScript 就是 Model X Plaid。嗚嗚嗚。
但因為它是 JavaScript 的超集,所以它實際上並不像 JavaScript 本身那樣運作。例如,JavaScript 是一種腳本語言,這意味著程式碼在執行過程中會被逐行解釋。它被設計成可以在不同作業系統和硬體配置的網路瀏覽器中運作。這與 C 等低階語言不同,後者需要先編譯為特定係統的機器碼才能執行。
因此,JavaScript 不必先編譯,而是由 JavaScript 引擎解釋。另一方面,TypeScript 必須先轉換(或「轉編譯」)為 JavaScript,然後才能由瀏覽器中的 JavaScript 引擎(或作為獨立的 NodeJS 應用程式)執行。
所以這個過程看起來有點像這樣:
→ Write TypeScript Code
→ “Transcompile” to JavaScript
→ Interpret JavaScript & Check for Errors
→ JavaScript Engine Compiles and Executes the Code
很有趣,對吧?
現在我們已經掌握了一些理論知識,接下來讓我們繼續討論一些更實際的東西,例如 TypeScript 的出名之處:它就是類型!
順便一提…
我們Wasp正在努力建立最好的開源 React/NodeJS 框架,讓您快速行動!
這就是為什麼我們提供了即用型全端應用程式模板,例如帶有 TypeScript 的 ToDo 應用程式。您所要做的就是安裝 Wasp:
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
並執行:
wasp new -t todo-ts
您將獲得一個開箱即用的具有 Auth 和端到端 TypeSafety 功能的全端 ToDo 應用程式,以幫助您學習 TypeScript,或者只是開始快速安全地建置一些東西:)
satisfies
還記得我如何向我的同事尋求幫助,他的解決方案涉及satisfies
關鍵字嗎?好吧,為了更好地理解它,我決定打開一個編輯器並嘗試一些基本範例,這是我發現的最有用的東西。
首先,我們以 person 物件為例,將其輸入為Record
,該 Record 可以採用一組PossibleKeys
和一個string
或number
作為值。那想看看這個:
type PossibleKeys = "id" | "name" | "email" | "age";
const person: Record<PossibleKeys, string | number> = { }
我們輸入person
常數的方式稱為型別註解。它直接位於變數名稱之後。
讓我們開始為此person
物件新增鍵和值:
type PossibleKeys = "id" | "name" | "email" | "age";
const person: Record<PossibleKeys, string | number> = {
id: 12,
name: "Vinny",
email: "[email protected]",
age: 37,
}
看起來很簡單,對吧?
現在,讓我們來看看 TypeScript 如何推斷person
屬性的類型:
有趣的。當我們將滑鼠懸停在email
上時,我們看到 TypeScript 告訴我們電子郵件是string
或number
的聯合類型,即使我們肯定只將其定義為string
。
如果我們嘗試在這種類型上使用一些string
方法,這將會產生一些意想不到的後果。讓我們嘗試一下split
方法,例如:
我們收到一個錯誤,表示此方法不適用於number
類型。哪個是對的。但這很煩人,因為我們知道email
是一個字串。
讓satisfies
透過將類型向下移動到常數定義的末尾來解決這個問題:
type PossibleKeys = "id" | "name" | "email" | "age";
const person = {
id: 12,
name: "Vinny",
email: "[email protected]",
age: 37,
} satisfies Record<PossibleKeys, string | number>;
現在,當將滑鼠懸停在email
屬性上時,我們將看到它被正確推斷為string
:
好的!現在,我們使用split
將email
轉換為字串陣列不會遇到任何問題。
這就是satisfies
真正的閃光點。它讓我們驗證表達式的類型是否與特定類型匹配,同時為我們推斷最窄的可能類型。
但當我玩satisfies
時,我注意到另一個奇怪的事情是,如果我直接在變數上使用它與在中間變數上使用它,它的行為會有所不同,如下所示:
// Directly on object literal
const person = { } satisfies PersonType;
// Using on intermediate variable
const personIntermediate = person satisfies PersonType
具體來說,如果我向person
物件加入類型中不存在的另一個屬性(例如isAdmin
,則直接使用時我們會收到錯誤,但使用中間變數時不會收到錯誤:
satisfies
satisfies
和中間變數您可以看到,在範例 2 中,沒有錯誤且 person “滿足” PersonType
,但在範例 1 中卻沒有。
這是為什麼?
嗯,這實際上與 JavaScript 的基本工作原理有關,而與satisfies
關鍵字關係不大。讓我們來看看。
上面範例中發生的過程就是所謂的「多餘屬性檢查」。
過多的屬性檢查實際上是該規則的例外。 TypeScript 使用所謂的「結構類型系統」。這只是一種奇特的方式來表示如果一個值具有所有預期的屬性,那麼它將被使用。
因此,使用上面的personIntermediate
範例,TypeScript 不會抱怨person
有一個額外的屬性isAdmin
,該屬性在PersonType
中不存在。它具有所有其他必要的屬性,例如id
、 name
、 email
和age
,因此 TypeScript 接受這種中間形式。
但是,當我們直接在變數上聲明類型時(如範例 1 中所示),我們會收到 TypeScript 錯誤:「'isAdmin' 在類型 'PersonType' 中不存在」。這是工作中的多餘屬性檢查,它可以幫助您避免犯下愚蠢的錯誤。
記住這一點是有好處的,因為這將幫助您避免意外的副作用。
例如,假設我們將 person 類型變更為具有可選的isAdmin
屬性,如下所示:
type PersonType = {
id: number,
name: string,
isAdmin?: boolean, // 👈 Optional
}
如果我們不小心用isadmin
屬性而不是isAdmin
定義了person
並且沒有直接聲明類型,會發生什麼情況?
我們不會從 TypeScript 中得到任何錯誤,因為person
實際上滿足所有必要的類型。 isAdmin
類型是可選的,它不存在於person
上,但這並不重要。您已經做了一個簡單的 type-o,現在嘗試存取isAdmin
屬性,但它不起作用:
哎呀!讓我們用類型註釋來修復它,我們立即聲明類型:
好的。因為我們在第 58 行使用了直接類型註釋,所以我們獲得了 TypeScript 多餘屬性檢查的好處。
謝謝,打字稿! 🙏
如果您發現此內容有用,並且想要查看更多類似內容,您可以在 GitHub 上給 Wasp 一顆星,輕鬆幫助我們! 。
{% cta https://www.github.com/wasp-lang/wasp %} ⭐️ GitHub 上的 Star Wasp 🙏 {% endcta %}
感謝您加入我的旅程的第 1 部分,以便更好地了解我們每天使用的工具。
這將是一個持續進行的系列,我將繼續以更具探索性、更少結構化的方式分享我所學到的東西。我希望您發現其中的某些部分有用或有趣。
讓我知道你接下來想看什麼!你喜歡這種風格嗎?你願意改變一些事情嗎?加入或刪除一些東西?或者你對最近學到的東西有什麼看法或類似的故事嗎?
如果是這樣,請在評論中告訴我們,我們下次見:)
原文出處:https://dev.to/wasp/ive-been-writing-typescript-without-understanding-it-5ef4