成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

TypeScript 中 Interface 與 Type 的區別?該用哪個比較好?

開發 前端
類型別名的右邊可以是任何類型,包括基本類型、元祖、類型表達式( & 或 | 等);而在接口聲明中,右邊必須為變量結構。

[[415498]]

本文轉載自微信公眾號「三分鐘學前端」,作者sisterAn。轉載本文請聯系三分鐘學前端公眾號。

接口 與 類型別名 的異同點

相同點

1. 都可以描述對象或函數

  1. // 接口 
  2. interface Sister { 
  3.   name: string; 
  4.   age: number; 
  5.  
  6. interface SetSister { 
  7.   (name: string, age: number): void; 
  8.  
  9. // 類型別名 
  10. type Sister = { 
  11.   name: string; 
  12.   age: number; 
  13. }; 
  14.  
  15. type SetSister = (name: string, age: number) => void; 

2. 都可以擴展

interface 和 type 可以混合擴展,也就是說 interface 可以擴展 type,type 也可以擴展 interface。

但需要注意的是,接口的擴展是繼承( extends )。類型別名的擴展就是交叉類型(通過 & 實現)

  1. // 接口 
  2. interface SisterAn { 
  3.     name: string; 
  4.  
  5. // 類型別名 
  6. type SisterRan = { 
  7.     age: number; 
  1. // 接口擴展接口 
  2. interface Sister extends SisterAn { 
  3.     age: number; 
  1. // 類型別名擴展類型別名 
  2. type SisterPro = SisterRan & { 
  3.     name: string; 
  1. // 接口擴展類型別名 
  2. interface Sister extends SisterRan { 
  3.     name: string; 
  1. // 類型別名擴展接口 
  2. type SisterPro = SisterAn & { 
  3.     age: number; 

區別

官方 中這樣介紹兩者的區別:

Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.

意思就是說幾乎接口的所有特性都可以通過類型別名來實現,主要區別在于:

1. 不同的聲明范圍

與接口不同,可以為任意的類型創建類型別名

類型別名的右邊可以是任何類型,包括基本類型、元祖、類型表達式( & 或 | 等);而在接口聲明中,右邊必須為變量結構。例如,下面的類型別名就不能轉換成接口

  1. type Name = string 
  2. type Text = string | { text: string }; 
  3. type Coordinates = [number, number]; 

2. 不同的擴展形式

接口是通過繼承的方式來擴展,類型別名是通過 & 來擴展

  1. // 接口擴展 
  2. interface SisterAn { 
  3.     name: string; 
  4. interface Sister extends SisterAn { 
  5.     age: number; 
  6.  
  7. // 類型別名擴展 
  8. type SisterRan = { 
  9.     age: number; 
  10. type SisterPro = SisterRan & { 
  11.     name: string; 

這里需要注意的是,接口擴展時,typescript 會檢查擴展的接口是否可以賦值給被擴展的接口

  1. // 接口擴展 
  2. interface SisterAn { 
  3.     name: string; 
  4.     age: string 
  5.  
  6. interface Sister extends SisterAn { 
  7.     name: string; 
  8.     age: number; 
  9. // 報錯: 
  10. //  Interface 'Sister' incorrectly extends interface 'SisterAn'
  11. //  Types of property 'age' are incompatible. 
  12. //  Type 'number' is not assignable to type 'string' 

但使用交集類型時就不會出現這種情況

  1. // 類型別名擴展 
  2. type SisterRan = { 
  3.  name: string; 
  4.     age: string; 
  5. type SisterPro = SisterRan & { 
  6.     name: string; 
  7.     age: number; 

類型別名擴展時,typescript 將盡其所能把擴展和被擴展的類型組合在一起,而不會拋出編譯時錯誤

3. 不同的重復定義表現形式

接口可以定義多次,多次的聲明會自動合并

  1. interface Sister { 
  2.     name: string; 
  3. interface Sister { 
  4.     age: number; 
  5.  
  6. const sisterAn: Sister = { 
  7.     name'sisterAn' 
  8. }  
  9. // 報錯:Property 'age' is missing in type '{ name: string; }' but required in type 'Sister' 
  10.  
  11. const sisterRan: Sister = { 
  12.     name'sisterRan',  
  13.     age: 12 
  14. // 正確 

但是類型別名如果定義多次,會報錯

  1. type Sister = { // Duplicate identifier 'Sister' 
  2.     name: string; 
  3.  
  4. type Sister = { // Duplicate identifier 'Sister' 
  5.     age: number; 

如何選擇 Interface 、 Type

雖然 官方 中說幾乎接口的所有特性都可以通過類型別名來實現,但建議優先選擇接口,接口滿足不了再使用類型別名,在 typescript 官網 Preferring Interfaces Over Intersections 有說明,具體內容如下:

大多數時候,對象類型的簡單類型別名的作用與接口非常相似

  1. interface Foo { prop: string } 
  2.  
  3. type Bar = { prop: string }; 

但是,一旦你需要組合兩個或多個類型來實現其他類型時,你就可以選擇使用接口擴展這些類型,或者使用類型別名將它們交叉在一個中(交叉類型),這就是差異開始的時候。

接口創建一個單一的平面對象類型來檢測屬性沖突,這通常很重要! 而交叉類型只是遞歸的進行屬性合并,在某種情況下可能產生 never 類型

接口也始終顯示得更好,而交叉類型做為其他交叉類型的一部分時,直觀上表現不出來,還是會認為是不同基本類型的組合。

接口之間的類型關系會被緩存,而交叉類型會被看成組合起來的一個整體。

最后一個值得注意的區別是,在檢查到目標類型之前會先檢查每一個組分。

出于這個原因,建議使用接口/擴展擴展類型而不是創建交叉類型。

  1. - type Foo = Bar & Baz & { 
  2. -     someProp: string; 
  3. - } 
  4. + interface Foo extends Bar, Baz { 
  5. +     someProp: string; 
  6. + } 

簡單的說,接口更加符合 JavaScript 對象的工作方式,簡單的說明下,當出現屬性沖突時:

  1. // 接口擴展 
  2. interface Sister { 
  3.     sex: number; 
  4.  
  5. interface SisterAn extends Sister { 
  6.     sex: string; 
  7. // index.ts(5,11): error TS2430: Interface 'SisterAn' incorrectly extends interface 'Sister'
  8. //  Types of property 'sex' are incompatible. 
  9. //    Type 'string' is not assignable to type 'number'
  1. // 交叉類型 
  2. type Sister1 = { 
  3.     sex: number; 
  4.  
  5. type Sister2 = { 
  6.     sex: string; 
  7.  
  8. type SisterAn = Sister1 & Sister2; 
  9. // 不報錯,此時的 SisterAn 是一個'number & string'類型,也就是 never 

來源:https://github.com/Advanced-Frontend/Daily-Interview-Question

 

責任編輯:武曉燕 來源: 三分鐘學前端
相關推薦

2022-09-02 09:02:44

TypeInterface

2022-05-06 09:21:21

TypeScriptinterfacetype

2021-11-11 07:02:33

類型函數調用

2021-11-30 23:01:51

編程語言數據Python

2019-08-28 15:38:04

Linux系統工具

2021-11-05 07:13:46

Python

2025-03-07 08:44:47

Typescriptiinterfacetype

2022-04-07 08:20:22

typeinterface前端

2021-06-23 08:01:18

TypeScript interface type

2020-01-17 13:33:42

大數據分析師大數據工程師

2018-06-16 14:32:16

無線路由器單頻雙頻

2010-03-29 17:38:18

CentOS源代碼

2021-03-15 14:09:49

電腦軟件安全

2020-09-23 09:08:05

typescript

2020-06-30 09:10:35

編程學習技術

2015-01-08 22:06:18

2009-09-15 09:24:42

思科認證考試思科認證

2022-03-13 23:31:13

JavaScript工具動畫庫

2020-09-23 16:53:46

Python編輯器工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩在线播放 | 国产精品视频在线观看 | 日韩欧美网 | 国产 欧美 日韩 一区 | 欧美偷偷 | 91在线一区二区 | 日韩在线视频一区 | 国产精品一区二区久久久久 | jlzzxxxx18hd护士 | 国产精品日韩欧美一区二区三区 | 亚洲视频免费一区 | 蜜桃久久 | 免费黄色大片 | 精精国产xxxx视频在线 | 国产精品久久久久久久久久免费 | 国产一区 | 一区二区手机在线 | 日韩三区在线观看 | 久久久久亚洲精品 | 在线日韩视频 | 亚洲一区日韩 | 91精品国产综合久久久久蜜臀 | 成人av一区二区亚洲精 | 亚洲人人 | 色秀网站 | 国产精品99久久久久久宅男 | 91久久夜色 | 日韩毛片在线观看 | 国产精品日韩欧美一区二区三区 | 午夜影院黄 | 国产精品久久久爽爽爽麻豆色哟哟 | 国产一区二 | 色啪网 | 国产精品一区视频 | 亚洲黄色国产 | 久草热播| 一区二区三区日 | 国产一区视频在线 | 青草青草久热精品视频在线观看 | 中文字幕乱码视频32 | 国产综合久久久久久鬼色 |