<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ū)別?該用哪個(gè)比較好?

          共 6197字,需瀏覽 13分鐘

           ·

          2021-08-11 10:01


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

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


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

          接口 與 類型別名 的異同點(diǎn)

          相同點(diǎn)

          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. 都可以擴(kuò)展

          interface 和 type 可以混合擴(kuò)展,也就是說 interface 可以擴(kuò)展 typetype 也可以擴(kuò)展 interface

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

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

          // 類型別名
          type SisterRan = {
              age: number;
          }
          // 接口擴(kuò)展接口
          interface Sister extends SisterAn {
              age: number;
          }
          // 類型別名擴(kuò)展類型別名
          type SisterPro = SisterRan & {
              name: string;
          }
          // 接口擴(kuò)展類型別名
          interface Sister extends SisterRan {
              name: string;
          }
          // 類型別名擴(kuò)展接口
          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.

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

          1. 不同的聲明范圍

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

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

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

          2. 不同的擴(kuò)展形式

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

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

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

          這里需要注意的是,接口擴(kuò)展時(shí),typescript 會(huì)檢查擴(kuò)展的接口是否可以賦值給被擴(kuò)展的接口

          // 接口擴(kuò)展
          interface SisterAn {
              name: string;
              age: string
          }

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

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

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

          類型別名擴(kuò)展時(shí),typescript 將盡其所能把擴(kuò)展和被擴(kuò)展的類型組合在一起,而不會(huì)拋出編譯時(shí)錯(cuò)誤

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

          接口可以定義多次,多次的聲明會(huì)自動(dòng)合并

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

          const sisterAn: Sister = {
              name: 'sisterAn'

          // 報(bào)錯(cuò):Property 'age' is missing in type '{ name: string; }' but required in type 'Sister'

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

          但是類型別名如果定義多次,會(huì)報(bào)錯(cuò)

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

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

          如何選擇 Interface 、 Type

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

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

          interface Foo { prop: string }

          type Bar = { prop: string };

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

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

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

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

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

          // 接口擴(kuò)展
          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;
          // 不報(bào)錯(cuò),此時(shí)的 SisterAn 是一個(gè)'number & string'類型,也就是 never


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

          最后

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

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

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


          瀏覽 78
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  美穴在线| 天天草天天干天天射 | 偷偷操av | 亚洲毛多水多 | 在线aaa|