一文學會 TypeScript 的 82% 常用知識點(上)

一文學會 TypeScript 的 82% 常用知識點(上)

對於前端從業者來說,TypeScript(以下簡稱 TS)已經不算是新技術。

Vue3 的源碼基於 TS 編寫, Angular 項目默認支持 TS 等。它出現的頻率越來越高,而學習難度並不大,大概一個週末可以熟悉。

投入少,產出大,所以最好還是花點時間學習一下。

本文根據 TS handbook 整理出 TS 關鍵的知識點,並對某些部分作了擴展,希望能幫助大家學習理解。

前言

在學習 TS 之前,需要理解它的兩個特點:

  1. TS 是 JS 的超集
  2. TS 給 JS 帶來類型系統

這意味著 TS 的根基是 JS,是在 JS 的 基礎上添加了類型系統。

一文學會 TypeScript 的 82% 常用知識點(上)

觀察上述代碼,在 JS 中,使用「等號=」給變量賦值

經過 TS 的擴展,可以使用「冒號:」給變量賦類型。代碼中聲明變量 foo 的類型是 string。

類型校驗

類型系統的另一個特點是進行類型校驗。

在 TS 中,需要校驗「等號=」左右的類型是否匹配。

一文學會 TypeScript 的 82% 常用知識點(上)

如上述代碼所示,值存在明確的類型,TS 會校驗左右兩側的類型是否匹配,若不匹配則提示錯誤。

在瞭解這些前置知識後,來看看具體的 TS 知識點。

一、基本類型

繼承 JS 的基本類型如:string、number、boolean、undefined、null。擴展了其他基本類型如:any、never、void。

1.1 string

表示類型為字符串

一文學會 TypeScript 的 82% 常用知識點(上)

1.2 number

表示類型為數字

一文學會 TypeScript 的 82% 常用知識點(上)

1.3 boolean

表示類型為布爾類型

一文學會 TypeScript 的 82% 常用知識點(上)

1.4 undefined

表示類型為 undefined

一文學會 TypeScript 的 82% 常用知識點(上)

1.5 null

表示類型為 null

一文學會 TypeScript 的 82% 常用知識點(上)

1.6 void

表示類型為 undefined 或 null。

1.6.1 對於變量

一個聲明為 void 類型的變量,只能被賦值為 undefined 或 null。這種應用場景較少。

一文學會 TypeScript 的 82% 常用知識點(上)

1.6.2 對於函數

void 用於表示函數沒有返回值,只是執行某些操作。這是 void 的普遍應用場景。

一文學會 TypeScript 的 82% 常用知識點(上)

一個沒有顯式返回的函數,默認 return undefined。符合 void 類型只能被賦值為 undefined 或 null。

1.7 never

表示永遠不存在值。

典型例子:一個只會拋出異常的函數,它的返回值並不存在。

一文學會 TypeScript 的 82% 常用知識點(上)

執行函數則拋出錯誤,連 undefined 都不會返回。

1.8 any

表示可能為任何類型。

典型例子:不確定變量的類型或類型是動態的。

一文學會 TypeScript 的 82% 常用知識點(上)

二、引用類型

TS 中的引用類型,除了 JS 中的數組類型、對象類型,還擴展了枚舉類型,元祖類型。

2.1 數組類型

表示由某(些)類型組成的數組。有兩種寫法:方括號表示法和尖括號表示法。

2.1.1 方括號表示法

一文學會 TypeScript 的 82% 常用知識點(上)

表示 arr 的類型是由數字組成的數組。

2.1.2 尖括號表示法

使用 Array,這是數組泛型的使用形式,關於泛型後續會展開。

一文學會 TypeScript 的 82% 常用知識點(上)

2.2 只讀數組

使用 ReadonlyArray 定義只讀數組。只讀數組只能在數組初始化時定義其值,創建後不能進行修改。

一文學會 TypeScript 的 82% 常用知識點(上)

只讀數組和常規數組類型 Array 類似。區別在於:常規數組存在修改數組的方法,只讀數組不存在修改數組的方法。

2.3 object

表示類型為對象。除了 string、number、bigint、boolean、 undefined、null、symbol 基本類型外的引用類型。

一文學會 TypeScript 的 82% 常用知識點(上)

2.4 元組

定長數組構成,數組中的元素是某(些)類型。

一文學會 TypeScript 的 82% 常用知識點(上)

2.5 枚舉

使用關鍵字 enum 定義枚舉類型。默認枚舉值從 0 開始,可以手動賦值。

一文學會 TypeScript 的 82% 常用知識點(上)

三、類型斷言

明確告訴 TS 某個值的類型。有兩種寫法:尖括號寫法、as 寫法。

尖括號寫法

一文學會 TypeScript 的 82% 常用知識點(上)

as 寫法

一文學會 TypeScript 的 82% 常用知識點(上)

注意事項

類型斷言和類型轉換是有明確區別,不能將它理解成類型轉換。

在闡述此注意事項之前,先引入另一個概念:聯合類型

一文學會 TypeScript 的 82% 常用知識點(上)

在上述代碼中,string | number 表示的就是一個聯合類型,意味著 answer 的類型可以為 string 或 number。

下面逐步解釋類型斷言和類型轉換之間的區別。

一文學會 TypeScript 的 82% 常用知識點(上)

上述代碼中,string | number 聯合類型包含 string 類型,所以這兩種類型之間存在聯繫。使用 as 將聯合類型斷言成更加具體的 string 類型。

一文學會 TypeScript 的 82% 常用知識點(上)

上述代碼中,將 number 類型斷言為 string | number 類型。同樣是因為兩種類型之間存在聯繫,所以也允許斷言。相當於將一個具體的 number 類型斷言成更加廣泛的聯合類型。

一文學會 TypeScript 的 82% 常用知識點(上)

而將 string 類型斷言為 number 類型,這是兩種不同的類型,沒有任何聯繫,斷言會提示錯誤。

觀察上述三個例子,斷言發生在兩種類型存在聯繫的情況,它並不是將一種類型

轉換成另一種類型。

有些腦瓜子靈活的朋友會想到,藉助兩次斷言來進行類似的類型轉換。

一文學會 TypeScript 的 82% 常用知識點(上)

這是欺騙了 TS 校驗,後果只能自己承擔。

四、接口

上面提到使用 object 描述對象類型。但是,對於具有複雜結構的對象、函數。上述的 object 類型力有不逮。

一文學會 TypeScript 的 82% 常用知識點(上)

上述代碼中,即使是空對象,也能通過 object 類型校驗,而不會校驗對象的結構是否能滿足後續使用。

此時,就需要使用接口。在 TS 中,接口是描述值的結構

一文學會 TypeScript 的 82% 常用知識點(上)

上述代碼中,就定義了一個接口來描述參數 o,要求它是一個對象,含有 name 屬性,且屬性值是字符串。

所以,不符合此結構的空對象 {} 就提示錯誤。

一般來說,使用關鍵字 interface 來定義接口。

重寫上述接口 ——

一文學會 TypeScript 的 82% 常用知識點(上)

4.1 固定屬性

在接口中,使用 屬性名:屬性類型 的結構定義固定屬性。

一文學會 TypeScript 的 82% 常用知識點(上)

如上述代碼所示,傳入的對象需要具有 name 和 age 兩個屬性,否則會報錯。

4.2 可選屬性

在接口中,使用 屬性名?:屬性類型 的結構定義可選屬性。顧名思義,可選屬性可以存在,也可以不存在。

一文學會 TypeScript 的 82% 常用知識點(上)

4.3 只讀屬性

在接口中,使用 readonly 屬性名:屬性類型 的結構定義只讀屬性。只讀屬性只能在屬性初始化時定義其值,定義後不能進行修改。

一文學會 TypeScript 的 82% 常用知識點(上)

4.4 額外檢查

TS 會對對象字面量進行額外的屬性檢查

一文學會 TypeScript 的 82% 常用知識點(上)

在上述代碼中,接口 Point 定義了兩個可選屬性,對象字面量中屬性 x 和接口兼容,屬性 z 是多餘無意義的。

雖然實際的屬性比接口定義的多,按照常規理解,這是可以通過類型校驗,但事實卻相反。

TS 對於對象字面量是會進行額外的屬性檢查,體現在:

當對象字面量賦值給變量或它直接作為參數傳遞給函數時,如果對象字面量的屬性沒有在接口中定義,則會報錯。

換句話說,對於對象字面量,當它直接賦值給變量和函數參數時,它的屬性不能比接口描述的多。

這裡重點是直接賦值,如果像例子中,先將對象字面量賦值給變量,再通過變量傳參,這樣間接的方法可以繞過額外的檢查。

4.5 可索引類型

可索引類型包括字符串索引類型

數字索引類型

4.5.1 字符串索引類型

字符串索引類型具有字符串索引簽名

一文學會 TypeScript 的 82% 常用知識點(上)

4.5.2 數字索引類型

數字索引類型具有數字索引簽名

一文學會 TypeScript 的 82% 常用知識點(上)

4.5.3 混合索引簽名

屬性和索引簽名可以形成混合索引簽名,但是屬性需要和索引簽名類型匹配。

一文學會 TypeScript 的 82% 常用知識點(上)

另外,TS 允許同時使用上述兩種簽名,但是數字索引返回值的類型,它必須是字符串索引返回值類型的子類型。

因為對於 JS 來說,當使用數字索引時,會將它轉換成字符串進行索引。所以它們需要保持一致。

一文學會 TypeScript 的 82% 常用知識點(上)

上述代碼中,ThreeD 是 TwoD 的子類型,所以接口 PointA 正確。

4.5.4 只讀索引簽名

可以將索引簽名設置為只讀,只能在數組初始化時定義其值,創建後不能進行修改。

一文學會 TypeScript 的 82% 常用知識點(上)

4.6 函數類型

函數類型具有調用簽名

一文學會 TypeScript 的 82% 常用知識點(上)

如上述代碼所示,調用簽名包括參數列表和返回值類型。

對於函數類型來說,它校驗的值當然是函數 ——

一文學會 TypeScript 的 82% 常用知識點(上)

如上述代碼所示,函數的參數名可以與簽名的參數名不同。關鍵是對應位置的參數類型需要相同。

4.7 類類型

這裡的概念有些複雜,如果有良好的 JS 基礎,會較易理解。

類的關鍵字是 Class,由 ES6 開始引入,並逐步完善。本質上 Class 屬於語法糖,是基於 prototype 原型鏈實現的。

一文學會 TypeScript 的 82% 常用知識點(上)

而無論是 ES5 或 ES6,屬性 age 是在創建的實例上,而方法 getAge() 是在實例的原型鏈上。

一文學會 TypeScript 的 82% 常用知識點(上)

而類本身,它是不存在 age 屬性 和 getAge() 方法的。

一文學會 TypeScript 的 82% 常用知識點(上)

當然,我們也可以給類本身定義屬性和方法。 但給類本身定義的屬性和方法並不能通過實例直接訪問。

一文學會 TypeScript 的 82% 常用知識點(上)

所以,類與實例的屬性和方法是割裂的。

TS 將描述類的屬性和方法部分稱為類的靜態部分類型,將描述實例的屬性和方法部分稱為

類的實例部分類型

一文學會 TypeScript 的 82% 常用知識點(上)

在上述代碼中,使用關鍵字 implements 描述類實現了接口。更準確的是:描述 類的實例部分 實現了接口。

實現該接口的類的實例,它是具有 age 屬性,getAge() 方法。而類本身(即類的靜態部分)具有何種屬性與方法,上述代碼沒有進行定義。

所以,這裡所說的類類型,實際上是類(實例的)類型

關於如何定義類的靜態部分的類型,在後續會詳細介紹。

4.8 接口繼承

接口的可以使用關鍵字 extends 定義繼承。一個接口可以繼承多個接口。

一文學會 TypeScript 的 82% 常用知識點(上)

4.9 混合類型

一個對象可能混合多種類型。

例如定義一個帶版本號的函數——

一文學會 TypeScript 的 82% 常用知識點(上)

值得注意,上述使用類型斷言,將函數斷言為 Fn,即使 fn 在創建時並不存在 version 屬性。

4.10 接口繼承類

當接口繼承類類型時候,表現在繼承類的成員和結構,但不包括其實現。

接口繼承類的一個場景是,定義一個子類的類類型。

一文學會 TypeScript 的 82% 常用知識點(上)

結語

由於文章篇幅問題,全文拆分成上下兩篇發佈。

本篇主要介紹了 TS 的基本類型,引用類型、類型斷言、接口等知識點,瞭解上述的知識點可以閱讀部分 TS 代碼。

下篇涉及函數、類、泛型等稍微複雜的知識點。

<strong>

你的點贊和轉發,是我創作的動力,希望支持。


分享到:


相關文章: