天天看點

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

1. TypeScript 初體驗

TypeScript(簡稱:TS)是 JavaScript 的超集(JS 有的 TS 都有)。

TypeScript = Type + JavaScript(在 JS 基礎之上,為 JS 添加了類型支援)。

TypeScript 是微軟開發的開源程式設計語言,可以在任何運作 JavaScript 的地方運作。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

1.1 TypeScript 為什麼要為 JS 添加類型支援?

背景:JS 的類型系統存在“先天缺陷”,JS 代碼中絕大部分錯誤都是類型錯誤(Uncaught TypeError)。問題:增加了找 Bug、改 Bug 的時間,嚴重影響開發效率。

從程式設計語言的動靜來區分,TypeScript 屬于靜态類型的程式設計語言,JS 屬于動态類型的程式設計語言。靜态類型:編譯期做類型檢查; 動态類型:執行期做類型檢查。

代碼編譯和代碼執行的順序:1 編譯 2 執行。

  • 對于 JS 來說:需要等到代碼真正去執行的時候才能發現錯誤(晚)。
  • 對于 TS 來說:在代碼編譯的時候(代碼執行前)就可以發現錯誤(早)。
  • 并且,配合 VSCode 等開發工具,TS 可以提前到在編寫代碼的同時就發現代碼中的錯誤,減少找 Bug、改 Bug 時間

1.2 TypeScript 相比 JS 的優勢

  1. 更早(寫代碼的同時)發現錯誤,減少找 Bug、改 Bug 時間,提升開發效率。
  2. 程式中任何位置的代碼都有代碼提示,随時随地的安全感,增強了開發體驗。
  3. 強大的類型系統提升了代碼的可維護性,使得重構代碼更加容易。
  4. 支援最新的 ECMAScript 文法,優先體驗最新的文法,讓你走在前端技術的最前沿。
  5. TS 類型推斷機制,不需要在代碼中的每個地方都顯示标注類型,讓你在享受優勢的同時,盡量降低了成本。

1.3 編譯并運作 TS 代碼

  1. 建立 hello.ts 檔案(注意:TS 檔案的字尾名為 .ts)。
  2. 将 TS 編譯為 JS:在終端中輸入指令,tsc hello.ts(此時,在同級目錄中會出現一個同名的 JS 檔案)。
  3. 執行 JS 代碼:在終端中輸入指令,node hello.js。

說明:所有合法的 JS 代碼都是 TS 代碼,有 JS 基礎隻需要學習 TS 的類型即可。注意:由 TS 編譯生成的 JS 檔案,代碼中就沒有類型資訊了。

2. TypeScript 常用類型

TypeScript 是 JS 的超集,TS 提供了 JS 的所有功能,并且額外的增加了:類型系統。

  • 所有的 JS 代碼都是 TS 代碼。
  • JS 有類型(比如,number/string 等),但是 JS 不會檢查變量的類型是否發生變化。而 TS 會檢查。TypeScript 類型系統的主要優勢:可以顯示标記出代碼中的意外行為,進而降低了發生錯誤的可能性。
  1. 類型注解
  2. 常用基礎類型

2.1 類型注解

示例代碼:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

說明:代碼中的 : number 就是類型注解。

作用:為變量添加類型限制。比如,上述代碼中,約定變量 age 的類型為 number(數值類型)。

解釋:約定了類型,就隻能給變量指派該類型的值,否則,就會報錯。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

2.2 常用基礎類型概述

可以将 TS 中的常用基礎類型細分為兩類:1. JS原有類型 2 .TS 新增類型。

  1. JS原有類型
  • 原始類型:number/string/boolean/null/undefined/symbol。
  • 對象類型:object(包括,數組、對象、函數等對象)。
  1. TS 新增類型
  • 聯合類型、自定義類型(類型别名)、接口、元組、字面量類型、枚舉、void、any 等。

2.3 原始類型

  1. 原始類型:number/string/boolean/null/undefined/symbol。特點:簡單。這些類型,全按照 JS 中類型的名稱來書寫。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

2.4 數組類型

對象類型:object(包括,數組、對象、函數等對象)。

特點:對象類型,在 TS 中更加細化,每個具體的對象都有自己的類型文法。

數組類型的兩種寫法:(推薦使用 number[] 寫法)

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

需求:數組中既有 number 類型,又有 string 類型,這個數組的類型應該如何寫?

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:| (豎線)在 TS 中叫做聯合類型(由兩個或多個其他類型組成的類型,表示可以是這些類型中的任意一種)。

注意:這是 TS 中聯合類型的文法,隻有一根豎線,不要與 JS 中的或(||)混淆了。

2.5 類型别名

類型别名(自定義類型):為任意類型起别名。

使用場景:當同一類型(複雜)被多次使用時,可以通過類型别名,簡化該類型的使用。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 type 關鍵字來建立類型别名。
  • 類型别名(比如,此處的 CustomArray),可以是任意合法的變量名稱。
  • 建立類型别名後,直接使用該類型别名作為變量的類型注解即可。

2.6 函數類型

函數的類型實際上指的是:函數參數和傳回值的類型。

為函數指定類型的兩種方式:1 單獨指定參數、傳回值的類型 2 同時指定參數、傳回值的類型。

  1. 單獨指定參數、傳回值的類型:
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
  1. 同時指定參數、傳回值的類型:
  • 解釋:當函數作為表達式時,可以通過類似箭頭函數形式的文法來為函數添加類型。
  • 注意:這種形式隻适用于函數表達式。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
  1. 如果函數沒有傳回值,那麼,函數傳回值類型為:void。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

使用函數實作某個功能時,參數可以傳也可以不傳。這種情況下,在給函數參數指定類型時,就用到可選參數了。

比如,數組的 slice 方法,可以 slice() 也可以 slice(1) 還可以 slice(1, 3)。

可選參數:在可傳可不傳的參數名稱後面添加 ?(問号)。

注意:可選參數隻能出現在參數清單的最後,也就是說可選參數後面不能再出現必選參數。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

2.7 對象類型

JS 中的對象是由屬性和方法構成的,而 TS 中對象的類型就是在描述對象的結構(有什麼類型的屬性和方法)。 對象類型的寫法:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

直接使用 {} 來描述對象結構。屬性采用屬性名: 類型的形式;方法采用方法名(): 傳回值類型的形式。

如果方法有參數,就在方法名後面的小括号中指定參數類型(比如:greet(name: string): void)。

在一行代碼中指定對象的多個屬性類型時,使用 ;(分号)來分隔。

如果一行代碼隻指定一個屬性類型(通過換行來分隔多個屬性類型),可以去掉 ;(分号)。

方法的類型也可以使用箭頭函數形式(比如:{ sayHi: () => void })。

對象的屬性或方法,也可以是可選的,此時就用到可選屬性了。

比如,我們在使用 axios({ … }) 時,如果發送 GET 請求,method 屬性就可以省略。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

可選屬性的文法與函數可選參數的文法一緻,都使用 ?(問号)來表示。

2.8 接口

當一個對象類型被多次使用時,一般會使用接口(interface)來描述對象的類型,達到複用的目的。

解釋:

  • 使用 interface 關鍵字來聲明接口。
  • 接口名稱(比如,此處的 IPerson),可以是任意合法的變量名稱。
  • 聲明接口後,直接使用接口名稱作為變量的類型。
  • 因為每一行隻有一個屬性類型,是以,屬性類型後沒有 ;(分号)。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    interface(接口)和 type(類型别名)的對比:
  • 相同點:都可以給對象指定類型。
  • 不同點:

    接口,隻能為對象指定類型。

    類型别名,不僅可以為對象指定類型,實際上可以為任意類型指定别名。

    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

如果兩個接口之間有相同的屬性或方法,可以将公共的屬性或方法抽離出來,通過繼承來實作複用。 比如,這兩個接口都有 x、y 兩個屬性,重複寫兩次,可以,但很繁瑣。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

更好的方式:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 extends(繼承)關鍵字實作了接口 Point3D 繼承 Point2D。
  • 繼承後,Point3D 就有了 Point2D 的所有屬性和方法(此時,Point3D 同時有 x、y、z 三個屬性)。

2.9 元組

場景:在地圖中,使用經緯度坐标來标記位置資訊。

可以使用數組來記錄坐标,那麼,該數組中隻有兩個元素,并且這兩個元素都是數值類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

使用 number[] 的缺點:不嚴謹,因為該類型的數組中可以出現任意多個數字。

更好的方式:元組(Tuple)。

元組類型是另一種類型的數組,它确切地知道包含多少個元素,以及特定索引對應的類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

元組類型可以确切地标記出有多少個元素,以及每個元素的類型。

該示例中,元素有兩個元素,每個元素的類型都是 number。

2.10 類型推論

在 TS 中,某些沒有明确指出類型的地方,TS 的類型推論機制會幫助提供類型。

換句話說:由于類型推論的存在,這些地方,類型注解可以省略不寫!

發生類型推論的 2 種常見場景:1 聲明變量并初始化時 2 決定函數傳回值時。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

注意:這兩種情況下,類型注解可以省略不寫!

推薦:能省略類型注解的地方就省略(偷懶,充分利用TS類型推論的能力,提升開發效率)。 技巧:如果不知道類型,可以通過滑鼠放在變量名稱上,利用 VSCode 的提示來檢視類型。

2.11 類型斷言

有時候你會比 TS 更加明确一個值的類型,此時,可以使用類型斷言來指定更具體的類型。

比如,

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

注意:getElementById 方法傳回值的類型是 HTMLElement,該類型隻包含所有标簽公共的屬性或方法,不包含 a 标簽特有的 href 等屬性。

是以,這個類型太寬泛(不具體),無法操作 href 等 a 标簽特有的屬性或方法。

解決方式:這種情況下就需要使用類型斷言指定更加具體的類型。

使用類型斷言:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 as 關鍵字實作類型斷言。
  • 關鍵字 as 後面的類型是一個更加具體的類型(HTMLAnchorElement 是 HTMLElement 的子類型)。
  • 通過類型斷言,aLink 的類型變得更加具體,這樣就可以通路 a 标簽特有的屬性或方法了。

另一種文法,使用 <> 文法,這種文法形式不常用知道即可:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

技巧:在浏覽器控制台,通過 console.dir() 列印 DOM 元素,在屬性清單的最後面,即可看到該元素的類型。

2.12 字面量類型

思考以下代碼,兩個變量的類型分别是什麼?

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

通過 TS 類型推論機制,可以得到答案:

變量 str1 的類型為:string。

變量 str2 的類型為:‘Hello TS’。

解釋:

str1 是一個變量(let),它的值可以是任意字元串,是以類型為:string。

str2 是一個常量(const),它的值不能變化隻能是 ‘Hello TS’,是以,它的類型為:‘Hello TS’。

注意:此處的 ‘Hello TS’,就是一個字面量類型。也就是說某個特定的字元串也可以作為 TS 中的類型。 除字元串外,任意的 JS 字面量(比如,對象、數字等)都可以作為類型使用。

使用模式:字面量類型配合聯合類型一起使用。 使用場景:用來表示一組明确的可選值清單。

比如,在貪吃蛇遊戲中,遊戲的方向的可選值隻能是上、下、左、右中的任意一個。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:參數 direction 的值隻能是 up/down/left/right 中的任意一個。

優勢:相比于 string 類型,使用字面量類型更加精确、嚴謹。

2.13 枚舉

枚舉的功能類似于字面量類型+聯合類型組合的功能,也可以表示一組明确的可選值。

枚舉:定義一組命名常量。它描述一個值,該值可以是這些命名常量中的一個。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 enum 關鍵字定義枚舉。
  • 約定枚舉名稱、枚舉中的值以大寫字母開頭。
  • 枚舉中的多個值之間通過 ,(逗号)分隔。
  • 定義好枚舉後,直接使用枚舉名稱作為類型注解。

注意:形參 direction 的類型為枚舉 Direction,那麼,實參的值就應該是枚舉 Direction 成員的任意一個。

通路枚舉成員:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:類似于 JS 中的對象,直接通過點(.)文法通路枚舉的成員。

問題:把枚舉成員作為了函數的實參,它的值是什麼呢?

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:通過将滑鼠移入 Direction.Up,可以看到枚舉成員 Up 的值為 0。

注意:枚舉成員是有值的,預設為:從 0 開始自增的數值。

我們把,枚舉成員的值為數字的枚舉,稱為:數字枚舉。 當然,也可以給枚舉中的成員初始化值。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

字元串枚舉:枚舉成員的值是字元串。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

注意:字元串枚舉沒有自增長行為,是以,字元串枚舉的每個成員必須有初始值。

枚舉是 TS 為數不多的非 JavaScript 類型級擴充(不僅僅是類型)的特性之一。

因為:其他類型僅僅被當做類型,而枚舉不僅用作類型,還提供值(枚舉成員都是有值的)。

也就是說,其他的類型會在編譯為 JS 代碼時自動移除。但是,枚舉類型會被編譯為 JS 代碼!

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

說明:枚舉與前面講到的字面量類型+聯合類型組合的功能類似,都用來表示一組明确的可選值清單。

一般情況下,推薦使用字面量類型+聯合類型組合的方式,因為相比枚舉,這種方式更加直覺、簡潔、高效。

2.14 any 類型

原則:不推薦使用 any!這會讓 TypeScript 變為 “AnyScript”(失去 TS 類型保護的優勢)。

因為當值的類型為 any 時,可以對該值進行任意操作,并且不會有代碼提示。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:以上操作都不會有任何類型錯誤提示,即使可能存在錯誤!

盡可能的避免使用 any 類型,除非臨時使用 any 來“避免”書寫很長、很複雜的類型!

其他隐式具有 any 類型的情況:1 聲明變量不提供類型也不提供預設值 2 函數參數不加類型。 注意:因為不推薦使用 any,是以,這兩種情況下都應該提供類型!

2.15 typeof

衆所周知,JS 中提供了 typeof 操作符,用來在 JS 中擷取資料的類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

實際上,TS 也提供了 typeof 操作符:可以在類型上下文中引用變量或屬性的類型(類型查詢)。

使用場景:根據已有變量的值,擷取該值的類型,來簡化類型書寫。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 typeof 操作符來擷取變量 p 的類型,結果與第一種(對象字面量形式的類型)相同。
  • typeof 出現在類型注解的位置(參數名稱的冒号後面)所處的環境就在類型上下文(差別于 JS 代碼)。
  • 注意:typeof 隻能用來查詢變量或屬性的類型,無法查詢其他形式的類型(比如,函數調用的類型)。

3. TypeScript 進階類型

概述

TS 中的進階類型有很多,重點學習以下進階類型:

  • class 類
  • 類型相容性
  • 交叉類型
  • 泛型 和 keyof
  • 索引簽名類型 和 索引查詢類型
  • 映射類型

3.1 class 類

TypeScript 全面支援 ES2015 中引入的 class 關鍵字,并為其添加了類型注解和其他文法(比如,可見性修飾符等)

class 基本使用,如下:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 根據 TS 中的類型推論,可以知道 Person 類的執行個體對象 p 的類型是 Person。
  • TS 中的 class,不僅提供了 class 的文法功能,也作為一種類型存在。

執行個體屬性初始化:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 聲明成員 age,類型為 number(沒有初始值)。
  • 聲明成員 gender,并設定初始值,此時,可省略類型注解(TS 類型推論 為 string 類型)。

構造函數:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 成員初始化(比如,age: number)後,才可以通過 this.age 來通路執行個體成員。
  • 需要為構造函數指定類型注解,否則會被隐式推斷為 any;構造函數不需要傳回值類型。

執行個體方法:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:方法的類型注解(參數和傳回值)與函數用法相同。

類繼承的兩種方式:1 extends(繼承父類) 2 implements(實作接口)。 說明:JS 中隻有 extends,而 implements 是 TS 提供的。

extends

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 通過 extends 關鍵字實作繼承。
  • 子類 Dog 繼承父類 Animal,則 Dog 的執行個體對象 dog 就同時具有了父類 Animal 和 子類 Dog 的所有屬性和方法。

implements

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 通過 implements 關鍵字讓 class 實作接口。
  • Person 類實作接口 Singable 意味着,Person 類中必須提供 Singable 接口中指定的所有方法和屬性。

類成員可見性:可以使用 TS 來控制 class 的方法或屬性對于 class 外的代碼是否可見。

可見性修飾符包括:1 public(公有的) 2 protected(受保護的) 3 private(私有的)。

  1. public:表示公有的、公開的,公有成員可以被任何地方通路,預設可見性。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    解釋:
  • 在類屬性或方法前面添加 public 關鍵字,來修飾該屬性或方法是共有的。
  • 因為 public 是預設可見性,是以,可以直接省略。
  1. protected:表示受保護的,僅對其聲明所在類和子類中(非執行個體對象)可見。
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 在類屬性或方法前面添加 protected 關鍵字,來修飾該屬性或方法是受保護的。
  • 在子類的方法内部可以通過 this 來通路父類中受保護的成員,但是,對執行個體不可見!
  1. private:表示私有的,隻在目前類中可見,對執行個體對象以及子類也是不可見的。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    解釋:
  • 在類屬性或方法前面添加 private 關鍵字,來修飾該屬性或方法是私有的。
  • 私有的屬性或方法隻在目前類中可見,對子類和執行個體對象也都是不可見的!

除了可見性修飾符之外,還有一個常見修飾符就是:readonly(隻讀修飾符)。

readonly:表示隻讀,用來防止在構造函數之外對屬性進行指派。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 readonly 關鍵字修飾該屬性是隻讀的,注意隻能修飾屬性不能修飾方法。
  • 注意:屬性 age 後面的類型注解(比如,此處的 number)如果不加,則 age 的類型為 18 (字面量類型)。
  • 接口或者 {} 表示的對象類型,也可以使用 readonly。

3.2 類型相容性

兩種類型系統:1 Structural Type System(結構化類型系統) 2 Nominal Type System(标明類型系統)。

TS 采用的是結構化類型系統,也叫做 duck typing(鴨子類型),類型檢查關注的是值所具有的形狀。

也就是說,在結構類型系統中,如果兩個對象具有相同的形狀,則認為它們屬于同一類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • Point 和 Point2D 是兩個名稱不同的類。
  • 變量 p 的類型被顯示标注為 Point 類型,但是,它的值卻是 Point2D 的執行個體,并且沒有類型錯誤。
  • 因為 TS 是結構化類型系統,隻檢查 Point 和 Point2D 的結構是否相同(相同,都具有 x 和 y 兩個屬性,屬性類型也相同)。
  • 但是,如果在 Nominal Type System 中(比如,C#、Java 等),它們是不同的類,類型無法相容。

注意:在結構化類型系統中,如果兩個對象具有相同的形狀,則認為它們屬于同一類型,這種說法并不準确。 更準确的說法:對于對象類型來說,y 的成員至少與 x 相同,則 x 相容 y(成員多的可以指派給少的)。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • Point3D 的成員至少與 Point 相同,則 Point 相容 Point3D。
  • 是以,成員多的 Point3D 可以指派給成員少的 Point。

除了 class 之外,TS 中的其他類型也存在互相相容的情況,包括:1 接口相容性 2 函數相容性 等。

接口之間的相容性,類似于 class。并且,class 和 interface 之間也可以相容。

除了 class 之外,TS 中的其他類型也存在互相相容的情況,包括:1 接口相容性 2 函數相容性 等。

  • 接口之間的相容性,類似于 class。并且,class 和 interface 之間也可以相容。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

函數之間相容性比較複雜,需要考慮:1 參數個數 2 參數類型 3 傳回值類型。

  1. 參數個數,參數多的相容參數少的(或者說,參數少的可以指派給多的)。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    解釋:
  • 參數少的可以指派給參數多的,是以,f1 可以指派給 f2。
  • 數組 forEach 方法的第一個參數是回調函數,該示例中類型為:(value: string, index: number, array: string[]) => void。
  • 在 JS 中省略用不到的函數參數實際上是很常見的,這樣的使用方式,促成了 TS 中函數類型之間的相容性。
  • 并且因為回調函數是有類型的,是以,TS 會自動推導出參數 item、index、array 的類型。
  1. 參數類型

    相同位置的參數類型要相同(原始類型)或相容(對象類型)。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:函數類型 F2 相容函數類型 F1,因為 F1 和 F2 的第一個參數類型相同。

相同位置的參數類型要相同或相容。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 注意,此處與前面講到的接口相容性沖突。
  • 技巧:将對象拆開,把每個屬性看做一個個參數,則,參數少的(f2)可以指派給參數多的(f3)。
  1. 傳回值類型,隻關注傳回值類型本身即可:
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 如果傳回值類型是原始類型,此時兩個類型要相同,比如,左側類型 F5 和 F6。
  • 如果傳回值類型是對象類型,此時成員多的可以指派給成員少的,比如,右側類型 F7 和 F8。

3.3 交叉類型

交叉類型(&):功能類似于接口繼承(extends),用于組合多個類型為一個類型(常用于對象類型)。

比如,

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:使用交叉類型後,新的類型 PersonDetail 就同時具備了 Person 和 Contact 的所有屬性類型。

相當于,

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

交叉類型(&)和接口繼承(extends)的對比:

  • 相同點:都可以實作對象類型的組合。
  • 不同點:兩種方式實作類型組合時,對于同名屬性之間,處理類型沖突的方式不同。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    說明:以上代碼,接口繼承會報錯(類型不相容);交叉類型沒有錯誤,可以簡單的了解為:
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

3.4 泛型

泛型是可以在保證類型安全前提下,讓函數等與多種類型一起工作,進而實作複用,常用于:函數、接口、class 中。 需求:建立一個 id 函數,傳入什麼資料就傳回該資料本身(也就是說,參數和傳回值類型相同)。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

比如,id(10) 調用以上函數就會直接傳回 10 本身。但是,該函數隻接收數值類型,無法用于其他類型。

為了能讓函數能夠接受任意類型,可以将參數類型修改為 any。但是,這樣就失去了 TS 的類型保護,類型不安全。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

泛型在保證類型安全(不丢失類型資訊)的同時,可以讓函數等與多種不同的類型一起工作,靈活可複用。

實際上,在 C#和 Java 等程式設計語言中,泛型都是用來實作可複用元件功能的主要工具之一。

建立泛型函數:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 文法:在函數名稱的後面添加 <>(尖括号),尖括号中添加類型變量,比如此處的 Type。
  • 類型變量 Type,是一種特殊類型的變量,它處理類型而不是值。
  • 該類型變量相當于一個類型容器,能夠捕獲使用者提供的類型(具體是什麼類型由使用者調用該函數時指定)。
  • 因為 Type 是類型,是以可以将其作為函數參數和傳回值的類型,表示參數和傳回值具有相同的類型。
  • 類型變量 Type,可以是任意合法的變量名稱。

調用泛型函數:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 文法:在函數名稱的後面添加 <>(尖括号),尖括号中指定具體的類型,比如,此處的 number。
  • 當傳入類型 number 後,這個類型就會被函數聲明時指定的類型變量 Type 捕獲到。
  • 此時,Type 的類型就是 number,是以,函數 id 參數和傳回值的類型也都是 number。

同樣,如果傳入類型 string,函數 id 參數和傳回值的類型就都是 string。

這樣,通過泛型就做到了讓 id 函數與多種不同的類型一起工作,實作了複用的同時保證了類型安全。

簡化調用泛型函數:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 在調用泛型函數時,可以省略 <類型> 來簡化泛型函數的調用。
  • 此時,TS 内部會采用一種叫做類型參數推斷的機制,來根據傳入的實參自動推斷出類型變量 Type 的類型。
  • 比如,傳入實參 10,TS 會自動推斷出變量 num 的類型 number,并作為 Type 的類型。

推薦:使用這種簡化的方式調用泛型函數,使代碼更短,更易于閱讀。

說明:當編譯器無法推斷類型或者推斷的類型不準确時,就需要顯式地傳入類型參數。

泛型限制:預設情況下,泛型函數的類型變量 Type 可以代表多個類型,這導緻無法通路任何屬性。

比如,id(‘a’) 調用函數時擷取參數的長度:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:Type 可以代表任意類型,無法保證一定存在 length 屬性,比如 number 類型就沒有 length。

此時,就需要為泛型添加限制來收縮類型(縮窄類型取值範圍)。

添加泛型限制收縮類型,主要有以下兩種方式:1 指定更加具體的類型 2 添加限制。

  1. 指定更加具體的類型
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    比如,将類型修改為 Type[](Type 類型的數組),因為隻要是數組就一定存在 length 屬性,是以就可以通路了。

添加泛型限制收縮類型,主要有以下兩種方式:1 指定更加具體的類型 2 添加限制。

2. 添加限制

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 建立描述限制的接口 ILength,該接口要求提供 length 屬性。
  • 通過 extends 關鍵字使用該接口,為泛型(類型變量)添加限制。
  • 該限制表示:傳入的類型必須具有 length 屬性。

注意:傳入的實參(比如,數組)隻要有 length 屬性即可,這也符合前面講到的接口的類型相容性。

泛型的類型變量可以有多個,并且類型變量之間還可以限制(比如,第二個類型變量受第一個類型變量限制)。

比如,建立一個函數來擷取對象中屬性的值:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 添加了第二個類型變量 Key,兩個類型變量之間使用(,)逗号分隔。

    keyof 關鍵字接收一個對象類型,生成其鍵名稱(可能是字元串或數字)的聯合類型。

  • 本示例中 keyof Type 實際上擷取的是 person 對象所有鍵的聯合類型,也就是:‘name’ | ‘age’。
  • 類型變量 Key 受 Type 限制,可以了解為:Key 隻能是 Type 所有鍵中的任意一個,或者說隻能通路對象中存在的屬性。

泛型接口:接口也可以配合泛型來使用,以增加其靈活性,增強其複用性。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 在接口名稱的後面添加 <類型變量>,那麼,這個接口就變成了泛型接口。
  • 接口的類型變量,對接口中所有其他成員可見,也就是接口中所有成員都可以使用類型變量。
  • 使用泛型接口時,需要顯式指定具體的類型(比如,此處的 IdFunc)。
  • 此時,id 方法的參數和傳回值類型都是 number;ids 方法的傳回值類型是 number[]。

實際上,JS 中的數組在 TS 中就是一個泛型接口。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:當我們在使用數組時,TS 會根據數組的不同類型,來自動将類型變量設定為相應的類型。

技巧:可以通過 Ctrl + 滑鼠左鍵(Mac:option + 滑鼠左鍵)來檢視具體的類型資訊。

泛型類:class 也可以配合泛型來使用。

比如,React 的 class 元件的基類 Component 就是泛型類,不同的元件有不同的 props 和 state。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:React.Component 泛型類兩個類型變量,分别指定 props 和 state 類型。

建立泛型類:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 類似于泛型接口,在 class 名稱後面添加 <類型變量>,這個類就變成了泛型類。
  • 此處的 add 方法,采用的是箭頭函數形式的類型書寫方式。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    類似于泛型接口,在建立 class 執行個體時,在類名後面通過 <類型> 來指定明确的類型。

泛型工具類型:TS 内置了一些常用的工具類型,來簡化 TS 中的一些常見操作。

說明:它們都是基于泛型實作的(泛型适用于多種類型,更加通用),并且是内置的,可以直接在代碼中使用。

這些工具類型有很多,主要學習以下幾個:

Partial<Type>

Readonly<Type>

Pick<Type, Keys>

Record<Keys, Type>

泛型工具類型 - Partial 用來構造(建立)一個類型,将 Type 的所有屬性設定為可選。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:構造出來的新類型 PartialProps 結構和 Props 相同,但所有屬性都變為可選的。

泛型工具類型 -

Readonly<Type>

用來構造一個類型,将 Type 的所有屬性都設定為 readonly(隻讀)。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:構造出來的新類型 ReadonlyProps 結構和 Props 相同,但所有屬性都變為隻讀的。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

當我們想重新給 id 屬性指派時,就會報錯:無法配置設定到 “id” ,因為它是隻讀屬性。

泛型工具類型 - Pick<Type, Keys> 從 Type 中選擇一組屬性來構造新類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • Pick 工具類型有兩個類型變量:1 表示選擇誰的屬性 2 表示選擇哪幾個屬性。
  • 其中第二個類型變量,如果隻選擇一個則隻傳入該屬性名即可。
  • 第二個類型變量傳入的屬性隻能是第一個類型變量中存在的屬性。
  • 構造出來的新類型 PickProps,隻有 id 和 title 兩個屬性類型。

泛型工具類型 - Record<Keys,Type> 構造一個對象類型,屬性鍵為 Keys,屬性類型為 Type。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • Record 工具類型有兩個類型變量:1 表示對象有哪些屬性 2 表示對象屬性的類型。
  • 建構的新對象類型 RecordObj 表示:這個對象有三個屬性分别為a/b/c,屬性值的類型都是 string[]。

3.5 索引簽名類型

絕大多數情況下,我們都可以在使用對象前就确定對象的結構,并為對象添加準确的類型。

使用場景:當無法确定對象中有哪些屬性(或者說對象中可以出現任意多個屬性),此時,就用到索引簽名類型了。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 使用 [key: string] 來限制該接口中允許出現的屬性名稱。表示隻要是 string 類型的屬性名稱,都可以出現在對象中。
  • 這樣,對象 obj 中就可以出現任意多個屬性(比如,a、b 等)。
  • key 隻是一個占位符,可以換成任意合法的變量名稱。
  • 隐藏的前置知識:JS 中對象({})的鍵是 string 類型的。

在 JS 中數組是一類特殊的對象,特殊在數組的鍵(索引)是數值類型。

并且,數組也可以出現任意多個元素。是以,在數組對應的泛型接口中,也用到了索引簽名類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • MyArray 接口模拟原生的數組接口,并使用 [n: number] 來作為索引簽名類型。
  • 該索引簽名類型表示:隻要是 number 類型的鍵(索引)都可以出現在數組中,或者說數組中可以有任意多個元素。
  • 同時也符合數組索引是 number 類型這一前提。

3.6 映射類型

映射類型:基于舊類型建立新類型(對象類型),減少重複、提升開發效率。

比如,類型 PropKeys 有 x/y/z,另一個類型 Type1 中也有 x/y/z,并且 Type1 中 x/y/z 的類型相同:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

這樣書寫沒錯,但 x/y/z 重複書寫了兩次。像這種情況,就可以使用映射類型來進行簡化。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 映射類型是基于索引簽名類型的,是以,該文法類似于索引簽名類型,也使用了 []。
  • Key in PropKeys 表示 Key 可以是 PropKeys 聯合類型中的任意一個,類似于 forin(let k in obj)。
  • 使用映射類型建立的新對象類型 Type2 和類型 Type1 結構完全相同。
  • 注意:映射類型隻能在類型别名中使用,不能在接口中使用。

映射類型除了根據聯合類型建立新類型外,還可以根據對象類型來建立:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • 首先,先執行 keyof Props 擷取到對象類型 Props 中所有鍵的聯合類型即,‘a’ | ‘b’ | ‘c’。
  • 然後,Key in … 就表示 Key 可以是 Props 中所有的鍵名稱中的任意一個。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

實際上,前面講到的泛型工具類型(比如,

Partial<Type>

)都是基于映射類型實作的。 比如,

Partial<Type>

的實作:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • keyof T 即 keyof Props 表示擷取 Props 的所有鍵,也就是:‘a’ | ‘b’ | ‘c’。
  • 在 [] 後面添加 ?(問号),表示将這些屬性變為可選的,以此來實作 Partial 的功能。
  • 冒号後面的 T[P] 表示擷取 T 中每個鍵對應的類型。比如,如果是 ‘a’ 則類型是 number;如果是 ‘b’ 則類型是 string。
  • 最終,新類型 PartialProps 和舊類型 Props 結構完全相同,隻是讓所有類型都變為可選了。

剛剛用到的 T[P] 文法,在 TS 中叫做索引查詢(通路)類型。

作用:用來查詢屬性的類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:

  • Props[‘a’] 表示查詢類型 Props 中屬性 ‘a’ 對應的類型 number。是以,TypeA 的類型為 number。
  • 注意:[] 中的屬性必須存在于被查詢類型中,否則就會報錯。

索引查詢類型的其他使用方式:同時查詢多個索引的類型

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:使用字元串字面量的聯合類型,擷取屬性 a 和 b 對應的類型,結果為: string | number。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:使用 keyof 操作符擷取 Props 中所有鍵對應的類型,結果為: string | number | boolean。

4. TypeScript 類型聲明檔案

幾乎所有的 JavaScript 應用都會引入許多第三方庫來完成任務需求。

這些第三方庫不管是否是用 TS 編寫的,最終都要編譯成 JS 代碼,才能釋出給開發者使用。

我們知道是 TS 提供了類型,才有了代碼提示和類型保護等機制。

但在項目開發中使用第三方庫時,你會發現它們幾乎都有相應的 TS 類型,這些類型是怎麼來的呢?類型聲明檔案 類型聲明檔案:用來為已存在的 JS 庫提供類型資訊。

這樣在 TS 項目中使用這些庫時,就像用 TS 一樣,都會有代碼提示、類型保護等機制了。

  • TS 的兩種檔案類型
  • 類型聲明檔案的使用說明

4.1 TS 中的兩種檔案類型

TS 中有兩種檔案類型:1 .ts 檔案 2 .d.ts 檔案。

  • .ts 檔案:
  1. 既包含類型資訊又可執行代碼。
  2. 可以被編譯為 .js 檔案,然後,執行代碼。
  3. 用途:編寫程式代碼的地方。
  • .d.ts 檔案:
  1. 隻包含類型資訊的類型聲明檔案。
  2. 不會生成 .js 檔案,僅用于提供類型資訊。
  3. 用途:為 JS 提供類型資訊。

總結:.ts 是 implementation(代碼實作檔案);.d.ts 是 declaration(類型聲明檔案)。

如果要為 JS 庫提供類型資訊,要使用 .d.ts 檔案。

4.2 類型聲明檔案的使用說明

在使用 TS 開發項目時,類型聲明檔案的使用包括以下兩種方式:

  • 使用已有的類型聲明檔案
  • 建立自己的類型聲明檔案

學習順序:先會用(别人的)再會寫(自己的)。

1 内置類型聲明檔案

内置類型聲明檔案:TS 為 JS 運作時可用的所有标準化内置 API 都提供了聲明檔案。

比如,在使用數組時,數組所有方法都會有相應的代碼提示以及類型資訊:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

實際上這都是 TS 提供的内置類型聲明檔案。

可以通過 Ctrl + 滑鼠左鍵(Mac:option + 滑鼠左鍵)來檢視内置類型聲明檔案内容。

比如,檢視 forEach 方法的類型聲明,在 VSCode 中會自動跳轉到 lib.es5.d.ts 類型聲明檔案中。

當然,像 window、document 等 BOM、DOM API 也都有相應的類型聲明(lib.dom.d.ts)。

2 第三方庫的類型聲明檔案。

目前,幾乎所有常用的第三方庫都有相應的類型聲明檔案。

第三方庫的類型聲明檔案有兩種存在形式:1 庫自帶類型聲明檔案 2 由 DefinitelyTyped 提供。

  • 庫自帶類型聲明檔案:比如,axios。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    解釋:這種情況下,正常導入該庫,TS 就會自動加載庫自己的類型聲明檔案,以提供該庫的類型聲明。
  • 由 DefinitelyTyped 提供。

DefinitelyTyped 是一個 github 倉庫,用來提供高品質 TypeScript 類型聲明。

可以通過 npm/yarn 來下載下傳該倉庫提供的 TS 類型聲明包,這些包的名稱格式為:@types/*。

比如,@types/react、@types/lodash 等。

說明:在實際項目開發時,如果你使用的第三方庫沒有自帶的聲明檔案,VSCode 會給出明确的提示。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:當安裝 @types/* 類型聲明包後,TS 也會自動加載該類聲明包,以提供該庫的類型聲明。

補充:TS 官方文檔提供了一個頁面,可以來查詢 @types/* 庫。

建立自己的類型聲明檔案:1 項目内共享類型 2 為已有 JS 檔案提供類型聲明。

  • 項目内共享類型:如果多個 .ts 檔案中都用到同一個類型,此時可以建立 .d.ts 檔案提供該類型,實作類型共享。

操作步驟:

  1. 建立 index.d.ts 類型聲明檔案。
  2. 建立需要共享的類型,并使用 export 導出(TS 中的類型也可以使用 import/export 實作子產品化功能)。
  3. 在需要使用共享類型的 .ts 檔案中,通過 import 導入即可(.d.ts 字尾導入時,直接省略)。
  • 為已有 JS 檔案提供類型聲明:
  1. 在将 JS 項目遷移到 TS 項目時,為了讓已有的 .js 檔案有類型聲明。
  2. 成為庫作者,建立庫給其他人使用。

注意:類型聲明檔案的編寫與子產品化方式相關,不同的子產品化方式有不同的寫法。但由于曆史原因,JS 子產品化的發展經曆過多種變化(AMD、CommonJS、UMD、ESModule 等),而 TS 支援各種子產品化形式的類型聲明。這就導緻

,類型聲明檔案相關内容又多又雜。

示範:基于最新的 ESModule(import/export)來為已有 .js 檔案,建立類型聲明檔案。

開發環境準備:使用 webpack 搭建,通過 ts-loader 處理 .ts 檔案。

TS 項目中也可以使用 .js 檔案。

在導入 .js 檔案時,TS 會自動加載與 .js 同名的 .d.ts 檔案,以提供類型聲明。

declare 關鍵字:用于類型聲明,為其他地方(比如,.js 檔案)已存在的變量聲明類型,而不是建立一個新的變量。

  1. 對于 type、interface 等這些明确就是 TS 類型的(隻能在 TS 中使用的),可以省略 declare 關鍵字。
  2. 對于 let、function 等具有雙重含義(在 JS、TS 中都能用),應該使用 declare 關鍵字,明确指定此處用于類型聲明

5. 在 React 中使用 TypeScript

React 項目中使用 TS。包括以下内容:

  • 使用 CRA 建立支援 TS 的項目
  • TS 配置檔案 tsconfig.json
  • React 中的常用類型

5.1 使用 CRA 建立支援 TS 的項目

React 腳手架工具 create-react-app(簡稱:CRA)預設支援 TypeScript。

建立支援 TS 的項目指令:npx create-react-app 項目名稱 --template typescript。

當看到以下提示時,表示支援 TS 的項目建立成功:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

相對于非 TS 項目,目錄結構主要由以下三個變化:

  • 項目根目錄中增加了 tsconfig.json 配置檔案:指定 TS 的編譯選項(比如,編譯時是否移除注釋)。
  • React 元件的檔案擴充名變為:*.tsx。
  • src 目錄中增加了 react-app-env.d.ts:React 項目預設的類型聲明檔案。
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
    TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

react-app-env.d.ts:React 項目預設的類型聲明檔案。

三斜線指令:指定依賴的其他類型聲明檔案,types 表示依賴的類型聲明檔案包的名稱。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

解釋:告訴 TS 幫我加載 react-scripts 這個包提供的類型聲明。

react-scripts 的類型聲明檔案包含了兩部分類型:

  • react、react-dom、node 的類型
  • 圖檔、樣式等子產品的類型,以允許在代碼中導入圖檔、SVG 等檔案。

TS 會自動加載該 .d.ts 檔案,以提供類型聲明(通過修改 tsconfig.json 中的 include 配置來驗證)。

5.2 TS 配置檔案 tsconfig.json

tsconfig.json 指定:項目檔案和項目編譯所需的配置項。

注意:TS 的配置項非常多(100+),以 CRA 項目中的配置為例來學習,其他的配置項用到時查文檔即可。

  • tsconfig.json 檔案所在目錄為項目根目錄(與 package.json 同級)。
  • tsconfig.json 可以自動生成,指令:tsc --init。

除了在 tsconfig.json 檔案中使用編譯配置外,還可以通過指令行來使用。 使用示範:tsc hello.ts --target es6。

注意:

  • tsc 後帶有輸入檔案時(比如,tsc hello.ts),将忽略 tsconfig.json 檔案。
  • tsc 後不帶輸入檔案時(比如,tsc),才會啟用 tsconfig.json。

推薦使用:tsconfig.json 配置檔案。

5.3 React 中的常用類型

前提說明:現在,基于 class 元件來講解 React+TS 的使用(最新的 React Hooks,在後面講解)。 在不使用 TS 時,可以使用 prop-types 庫,為 React 元件提供類型檢查。

說明:TS 項目中,推薦使用 TypeScript 實作元件類型校驗(代替 PropTypes)。

不管是 React 還是 Vue,隻要是支援 TS 的庫,都提供了很多類型,來滿足該庫對類型的需求。

注意:

  • React 項目是通過 @types/react、@types/react-dom 類型聲明包,來提供類型的。
  • 這些包 CRA 已幫我們安裝好(react-app-env.d.ts),直接用即可。

React 是元件化開發模式,React 開發主要任務就是寫元件,兩種元件:1 函數元件 2 class 元件。

  1. 函數元件,主要包括以下内容:
  • 元件的類型
  • 元件的屬性(props)
  • 元件屬性的預設值(defaultProps)
  • 事件綁定和事件對象

函數元件的類型以及元件的屬性

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

實際上,還可以直接簡化為(完全按照函數在 TS 中的寫法):

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

函數元件屬性的預設值(defaultProps)

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

實際上,還可以直接簡化為(完全按照函數在 TS 中的寫法):

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

事件綁定和事件對象

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

再比如,文本框:

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

技巧:在 JSX 中寫事件處理程式(e => {}),然後,把滑鼠放在 e 上,利用 TS 的類型推論來檢視事件對象類型。

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

2. class 元件,主要包括以下内容:

  • 元件的類型、屬性、事件
  • 元件狀态(state)

class 元件的類型

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

class 元件的屬性和屬性預設值

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

class 元件狀态(state)和事件

TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript
TypeScript學習筆記1. TypeScript 初體驗2. TypeScript 常用類型3. TypeScript 進階類型4. TypeScript 類型聲明檔案5. 在 React 中使用 TypeScript

繼續閱讀