<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 6197字,需瀏覽 13分鐘

           ·

          2021-08-18 14:18

          點擊上方 三分鐘學(xué)前端,關(guān)注公眾號

          回復(fù)交流,加入前端編程面試算法每日一題群


          面試官也在看的前端面試資料

          接口 與 類型別名 的異同點

          相同點

          1. 都可以描述對象或函數(shù)

          // 接口
          interface Sister {
            name: string;
            age: number;
          }

          interface SetSister {
            (name: string, age: number): void;
          }

          // 類型別名
          type Sister = {
            name: string;
            age: number;
          };

          type SetSister = (name: string, age: number) => void;

          2. 都可以擴展

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

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

          // 接口
          interface SisterAn {
              name: string;
          }

          // 類型別名
          type SisterRan = {
              age: number;
          }
          // 接口擴展接口
          interface Sister extends SisterAn {
              age: number;
          }
          // 類型別名擴展類型別名
          type SisterPro = SisterRan & {
              name: string;
          }
          // 接口擴展類型別名
          interface Sister extends SisterRan {
              name: string;
          }
          // 類型別名擴展接口
          type SisterPro = SisterAn & {
              age: number;
          }

          區(qū)別

          官方 中這樣介紹兩者的區(qū)別:

          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.

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

          1. 不同的聲明范圍

          與接口不同,可以為任意的類型創(chuàng)建類型別名

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

          type Name = string
          type Text = string | { text: string };
          type Coordinates = [numbernumber];

          2. 不同的擴展形式

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

          // 接口擴展
          interface SisterAn {
              name: string;
          }
          interface Sister extends SisterAn {
              age: number;
          }

          // 類型別名擴展
          type SisterRan = {
              age: number;
          }
          type SisterPro = SisterRan & {
              name: string;
          }

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

          // 接口擴展
          interface SisterAn {
              name: string;
              age: string
          }

          interface Sister extends SisterAn {
              name: string;
              age: number;
          }
          // 報錯:
          //  Interface 'Sister' incorrectly extends interface 'SisterAn'.
          //  Types of property 'age' are incompatible.
          //  Type 'number' is not assignable to type 'string'

          但使用交集類型時就不會出現(xiàn)這種情況

          // 類型別名擴展
          type SisterRan = {
           name: string;
              age: string;
          }
          type SisterPro = SisterRan & {
              name: string;
              age: number;
          }

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

          3. 不同的重復(fù)定義表現(xiàn)形式

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

          interface Sister {
              name: string;
          }
          interface Sister {
              age: number;
          }

          const sisterAn: Sister = {
              name: 'sisterAn'

          // 報錯:Property 'age' is missing in type '{ name: string; }' but required in type 'Sister'

          const sisterRan: Sister = {
              name: 'sisterRan'
              age: 12
          }
          // 正確

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

          type Sister = { // Duplicate identifier 'Sister'
              name: string;
          }

          type Sister = { // Duplicate identifier 'Sister'
              age: number;
          }

          如何選擇 Interface 、 Type

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

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

          interface Foo { prop: string }

          type Bar = { prop: string };

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

          • 接口創(chuàng)建一個單一的平面對象類型來檢測屬性沖突,這通常很重要!  而交叉類型只是遞歸的進行屬性合并,在某種情況下可能產(chǎn)生 never 類型
          • 接口也始終顯示得更好,而交叉類型做為其他交叉類型的一部分時,直觀上表現(xiàn)不出來,還是會認為是不同基本類型的組合。
          • 接口之間的類型關(guān)系會被緩存,而交叉類型會被看成組合起來的一個整體。
          • 最后一個值得注意的區(qū)別是,在檢查到目標(biāo)類型之前會先檢查每一個組分。

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

          type Foo = Bar & Baz & {
          -     someProp: string;
          - }
          interface Foo extends Bar, Baz {
          +     someProp: string;
          + }

          簡單的說,接口更加符合 JavaScript 對象的工作方式,簡單的說明下,當(dāng)出現(xiàn)屬性沖突時:

          // 接口擴展
          interface Sister {
              sex: number;
          }

          interface SisterAn extends Sister {
              sex: string;
          }
          // index.ts(5,11): error TS2430: Interface 'SisterAn' incorrectly extends interface 'Sister'.
          //  Types of property 'sex' are incompatible.
          //    Type 'string' is not assignable to type 'number'.
          // 交叉類型
          type Sister1 = {
              sex: number;
          }

          type Sister2 = {
              sex: string;
          }

          type SisterAn = Sister1 & Sister2;
          // 不報錯,此時的 SisterAn 是一個'number & string'類型,也就是 never


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

          最后

          歡迎關(guān)注「三分鐘學(xué)前端」,回復(fù)「交流」自動加入前端三分鐘進階群,每日一道編程算法面試題(含解答),助力你成為更優(yōu)秀的前端開發(fā)!

          號內(nèi)回復(fù):

          網(wǎng)絡(luò)」,自動獲取三分鐘學(xué)前端網(wǎng)絡(luò)篇小書(90+頁)
          JS」,自動獲取三分鐘學(xué)前端 JS 篇小書(120+頁)
          算法」,自動獲取 github 2.9k+ 的前端算法小書
          面試」,自動獲取 github 23.2k+ 的前端面試小書
          簡歷」,自動獲取程序員系列的 120 套模版
          》》面試官也在看的前端面試資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的


          瀏覽 90
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久婷婷色香五月综合 | 人人爱人人射 | 午夜久久久久久 | 大鸡巴视频在线观看免费 | 青青草,新红楼丁香在线 |