[TypeScript] 介面 Part I (Interface Part I)

Hi 大家好,我是 Charlie 。

TypeScript 的出現讓前端語言有了架構檢查的機制,而在撰寫其他語言時,我們最熟悉不過的機制莫過於介面 (Interface) 了。 Interface 讓 Class, Function 對於參數、屬性的要求更嚴謹,以利開發及維護。 而 Interface 的篇幅相對較大,在這裡我會分成兩個部分來說明。

首先,確保我們都站一樣的基準點上,請知道 TypeScript 當初的誕生解決了許多 JavaScript 為人詬病的特性( Ex. 欠缺強型別、結構難以掌握、似有若無的介面規範…等等)。 TypeScript 完全基於 JavaScript 語法,在編譯後會生成 *.js 的程式碼以供使用。
Your First Interface

從上面的例子來看,我們可以看到 showYourName 這個 Function 它需要被傳入一個物件參數並定義期必須包含一個名為 name 且類型為字串的屬性。在呼叫 showYourName 方法時,系統會檢查參數的名稱與型態是否相符合,否則會報 error。但在實際應用上我們傳入的物件並不會只剛剛好擁有相同數量又剛好能夠匹配的屬性,該怎麼做呢? 我會在之後說明。

Optional Properties

在實際情況中,有些屬性只存在於某種特定條件之下,反之,它根本不會存在。為了這樣的情況,我們可以在 Interface 架構時在屬性名稱後加上 【?】符號,告訴系統這些屬性是架構之一但不一定要有值。 如例子所示,我再引用 showYourName 方法時並沒有傳入 gendar 屬性。 Interface 使用選擇性屬性的另外一個好處是它始終還是保有 Interface 的特性,當我在方法內使用不屬於 Interface的屬性時,而系統也會告訴我。

Readonly properties

當我們希望屬性在宣告完之後便不能進行更改,我們可以加上 readonly 前綴詞,以防止屬性被更改。

readonly or const?

這時大家應該會有疑問, readonly 和之前介紹的 const 有什麼差別呢? 答案是有哦, 假如你宣告的是變數的話就用 const 、是屬性的話就用 readonly

Excess Property Checks

好的,終於要解答第一階段我所提出的問題了。

在實際應用上我們傳入的物件並不會只剛剛好擁有相同數量又剛好能夠匹配的屬性,該怎麼做呢?

即便我們已經學會了在屬性後加入【?】的選擇性屬性,卻無法避免我們在呼叫 showYourName 時因為放入其他屬性而報 error。 到底我該怎麼樣才能讓系統像 C# 實作介面那樣只檢查我是否擁有既定屬性,而仍舊保有我物件的完整性? 方法有三個:

1️⃣使用型態斷言( Type Assertion )

型態斷言( Type Assertion )是編譯時期的靜態轉型,我們將物件轉換為 Interface定義的型態,透過這樣的方式我們可以繞過 Interface 給予的髮夾彎把我們傳入的參數安全無虞的放入 Function 內。但畢竟 Function 的參數型態還是有嚴謹的介面定義,要注意的是傳入的屬性並沒辦法在方法內使用。

2️⃣禁術.物件放入變數之術

你看!只要把物件放入隨便一個宣告的變數再傳入 Function 就可以繞過檢查囉! 我在 TypeScript 的文件上找到的具體原理是說變數並不會通過方法額外的屬性檢查,所以才不會報錯。 文件內也說明,不能因簡單的例子就認為這樣的方法可行,若是在內部處理相較複雜的 Function 下使用這種方法不僅會造成物件型態難以追蹤,也沒有達到 Interface 約束的意義了。

3️⃣添加索引標籤( Index Signature )

正統且較佳的用法是在 Interface內宣告索引標籤,當然它有個前提,就是物件所包含的屬性都有它使用的價值。如上所示,只要不符合 name 的屬性將都會被獨立宣告,且在 Function 內都可被使用。

以上是第一部分的說明,接下來我會在第二部分講解更多關於 Interface的應用,舉凡約束 Function、與 C# 等語言一樣針對 Class 進行 implements… 等等。

To be continue…
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.