<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 使用詳解

          共 10409字,需瀏覽 21分鐘

           ·

          2022-02-14 23:15


          前端獵手
          ?鏈接每一位開發(fā)者,讓編程更有趣兒!
          關(guān)注

          我是法醫(yī),一只治療系前端碼猿??,與代碼對(duì)話,傾聽它們心底的呼聲,期待著大家的點(diǎn)贊??與關(guān)注?,當(dāng)然也歡迎加入前端獵手技術(shù)交流群??,文末掃碼我拉你進(jìn)群,一起交流技術(shù)以及代碼之外的一切???♀?

          在 TypeScript中,接口是一個(gè)很重要的特性,它讓 TypeScript 具備了 JavaScript 所缺少的、描述較為復(fù)雜數(shù)據(jù)結(jié)構(gòu)的能力。下面就來(lái)看看什么是接口類型。

          一、接口定義

          接口是一系列抽象方法的聲明,是一些方法特征的集合,這些方法都應(yīng)該是抽象的,需要由具體的類去實(shí)現(xiàn),然后第三方就可以通過這組抽象方法調(diào)用,讓具體的類執(zhí)行具體的方法。

          TypeScript 的核心原則之一是對(duì)值所具有的結(jié)構(gòu)進(jìn)行類型檢查,并且只要兩個(gè)對(duì)象的結(jié)構(gòu)一致,屬性和方法的類型一致,則它們的類型就是一致的。?在TypeScript里,接口的作用就是為這些類型命名和為代碼或第三方代碼定義契約。

          TypeScript 接口定義形式如下:

          interface?interface_name?{?}

          來(lái)看例子,函數(shù)的參數(shù)是一個(gè)對(duì)象,它包含兩個(gè)字段:firstName 和 lastName,返回一個(gè)拼接后的完整名字:

          const?getFullName?=?({?firstName,?lastName?})?=>?{
          ??return?`${firstName}?${lastName}`;
          };

          調(diào)用時(shí)傳入?yún)?shù):

          getFullName({
          ??firstName:?"Hello",
          ??lastName:?"TypeScript"
          });?

          這樣調(diào)用是沒有問題的,但是如果傳入的參數(shù)不是想要的參數(shù)格式時(shí),就會(huì)出現(xiàn)一些錯(cuò)誤:

          getFullName();?//?Uncaught?TypeError:?Cannot?destructure?property?`a`?of?'undefined'?or?'null'.
          getFullName({?age:?18,?phone:?110?});?//?'undefined?undefined'
          getFullName({?firstName:?"Hello"?});?//?'Hello?undefined'

          這些都是我們不想要的,在開發(fā)時(shí)難免會(huì)傳入錯(cuò)誤的參數(shù),所以 TypeScript 能夠在編譯階段就檢測(cè)到這些錯(cuò)誤。下面來(lái)完善下這個(gè)函數(shù)的定義:

          const?getFullName?=?({
          ??firstName,
          ??lastName,
          }:?{
          ??firstName:?string;?//?指定屬性名為firstName和lastName的字段的屬性值必須為string類型
          ??lastName:?string;
          })?=>?{
          ??return?`${firstName}?${lastName}`;
          };

          通過對(duì)象字面量的形式去限定傳入的這個(gè)對(duì)象的結(jié)構(gòu),現(xiàn)在再來(lái)看下之前的調(diào)用會(huì)出現(xiàn)什么提示:

          getFullName();?//?應(yīng)有1個(gè)參數(shù),但獲得0個(gè)
          getFullName({?age:?18,?phone:?110?});?//?類型“{ age: number; phone: number;?}”的參數(shù)不能賦給類型“{ firstName: string; lastName: string;?}”的參數(shù)。
          getFullName({?firstName:?"Hello"?});?//?缺少必要屬性lastName

          這些都是在編寫代碼時(shí) TypeScript 提示的錯(cuò)誤信息,這樣就避免了在使用函數(shù)的時(shí)候傳入不正確的參數(shù)。我們可以使用interface來(lái)定義接口:

          interface?Info?{
          ??firstName:?string;
          ??lastName:?string;
          }
          const?getFullName?=?({?firstName,?lastName?}:?Info)?=>
          ??return?`${firstName}?${lastName}`;
          };

          注意:在定義接口時(shí),不要把它理解為是在定義一個(gè)對(duì)象,{}括號(hào)包裹的是一個(gè)代碼塊,里面是聲明語(yǔ)句,只不過聲明的不是變量的值而是類型。聲明也不用等號(hào)賦值,而是冒號(hào)指定類型。每條聲明之前用換行分隔即可,也可以使用分號(hào)或者逗號(hào)。

          二、接口屬性

          1. 可選屬性

          在定義一些結(jié)構(gòu)時(shí),一些結(jié)構(gòu)的某些字段的要求是可選的,有這個(gè)字段就做處理,沒有就忽略,所以針對(duì)這種情況,TypeScript提供了可選屬性。

          定義一個(gè)函數(shù):

          const?getVegetables?=?({?color,?type?})?=>?{
          ??return?`A?${color???color?+?"?"?:?""}${type}`;
          };

          這個(gè)函數(shù)中根據(jù)傳入對(duì)象中的 color 和 type 來(lái)進(jìn)行描述返回一句話,color 是可選的,所以可以給接口設(shè)置可選屬性,在屬性名后面加個(gè)?即可:

          interface?Vegetables?{
          ??color?:?string;
          ??type:?string;
          }

          const?getVegetables?=?({?color,?type?}:?Vegetables)?=>?{
          ??return?`A?${color???color?+?"?"?:?""}${type}`;
          };

          這里可能會(huì)報(bào)一個(gè)警告:接口應(yīng)該以大寫的i開頭,可以在 tslint.json 的 rules 里添加"interface-name": [true, “never-prefix”]來(lái)關(guān)閉這條規(guī)則。

          當(dāng)屬性被標(biāo)注為可選后,它的類型就變成了顯式指定的類型與 undefined 類型組成的聯(lián)合類型,比如 getVegetables 方法的參數(shù)中的 color 屬性類型就變成了這樣:

          string?|?undefined;

          那下面的接口與上述接口是一樣的嗎?

          interface?Vegetables2?{
          ??color?:?string?|?undefined;
          ??type:?string;
          }

          答案肯定是否定的,因?yàn)榭蛇x意味著可以不設(shè)置屬性鍵名,類型是 undefined 意味著屬性鍵名不可選。

          2. 只讀屬性

          接口可以設(shè)置只讀屬性,如下:

          interface?Role?{
          ??readonly?0:?string;
          ??readonly?1:?string;
          }

          這里定義了一個(gè)角色,有 0 和 1 兩種角色 id。下面定義一個(gè)角色數(shù)據(jù),并修改一下它的值:

          const?role:?Role?=?{
          ??0:?"super_admin",
          ??1:?"admin"
          };
          role[1]?=?"super_admin";?//?Cannot?assign?to?'0'?because?it?is?a?read-only?property

          這里TypeScript 提示不能分配給索引0,因?yàn)樗侵蛔x屬性。

          在ES6中,使用const定義的常量定義之后不能再修改,這和只讀意思接近。那readonlyconst在使用時(shí)該如何選擇呢?那主要看這個(gè)值的用途,如果是定義一個(gè)常量,那用const,如果這個(gè)值是作為對(duì)象的屬性,就用readonly

          const?NAME:?string?=?"TypeScript";
          NAME?=?"Haha";?//?Uncaught?TypeError:?Assignment?to?constant?variable
          const?obj?=?{
          ??name:?"TypeScript"
          };
          obj.name?=?"Haha";

          interface?Info?{
          ??readonly?name:?string;
          }
          const?info:?Info?=?{
          ??name:?"TypeScript"
          };
          info["name"]?=?"Haha";?//?Cannot?assign?to?'name'?because?it?is?a?read-only?property

          上面使用const定義的常量NAME定義之后再修改會(huì)報(bào)錯(cuò),但是如果使用const定義一個(gè)對(duì)象,然后修改對(duì)象里屬性的值是不會(huì)報(bào)錯(cuò)的。所以如果要保證對(duì)象的屬性值不可修改,需要使用readonly

          需要注意,readonly只是靜態(tài)類型檢測(cè)層面的只讀,實(shí)際上并不能阻止對(duì)對(duì)象的修改。因?yàn)樵谵D(zhuǎn)譯為 JavaScript 之后,readonly 修飾符會(huì)被抹除。因此,任何時(shí)候與其直接修改一個(gè)對(duì)象,不如返回一個(gè)新的對(duì)象,這是一種比較安全的方式。

          3. 多余屬性檢查

          先來(lái)看下面的例子:

          interface?Vegetables?{
          ??color?:?string;
          ??type:?string;
          }

          const?getVegetables?=?({?color,?type?}:?Vegetables)?=>?{
          ??return?`A?${color???color?+?"?"?:?""}${type}`;
          };

          getVegetables({
          ??type:?"tomato",
          ??size:?"big"?????//?'size'不在類型'Vegetables'中
          });

          這里沒有傳入 color 屬性,因?yàn)樗且粋€(gè)可選屬性,所以沒有報(bào)錯(cuò)。但是多傳入了一個(gè) size 屬性,這時(shí)就會(huì)報(bào)錯(cuò),TypeScript就會(huì)提示接口上不存在這個(gè)多余的屬性,所以只要是接口上沒有定義這個(gè)屬性,在調(diào)用時(shí)出現(xiàn)了,就會(huì)報(bào)錯(cuò)。

          注意:?這里可能會(huì)報(bào)一個(gè)警告:屬性名沒有按開頭字母順序排列屬性列表,可以在 tslint.json 的 rules 里添加"object-literal-sort-keys": [false]來(lái)關(guān)閉這條規(guī)則。

          有時(shí) 不希望TypeScript這么嚴(yán)格的對(duì)數(shù)據(jù)進(jìn)行檢查,比如上面的函數(shù),只需要保證傳入getVegetables的對(duì)象有type屬性就可以了,至于實(shí)際使用的時(shí)候傳入對(duì)象有沒有多余的屬性,多余屬性的屬性值是什么類型,我們就不管了,那就需要繞開多余屬性檢查,有如下方式:

          (1) 使用類型斷言

          類型斷言就是告訴 TypeScript,已經(jīng)自行進(jìn)行了檢查,確保這個(gè)類型沒有問題,希望 TypeScript 對(duì)此不進(jìn)行檢查,這是最簡(jiǎn)單的實(shí)現(xiàn)方式,類型斷言使用 as 關(guān)鍵字來(lái)定義(這里不細(xì)說,后面進(jìn)階篇會(huì)專門介紹類型斷言):

          interface?Vegetables?{
          ??color?:?string;
          ??type:?string;
          }

          const?getVegetables?=?({?color,?type?}:?Vegetables)?=>?{
          ??return?`A?${color???color?+?"?"?:?""}${type}`;
          };

          getVegetables({
          ??type:?"tomato",
          ??size:?12,
          ??price:?1.2
          }?as?Vegetables);

          (2) 添加索引簽名

          更好的方式是添加字符串索引簽名:

          interface?Vegetables?{
          ??color:?string;
          ??type:?string;
          ??[prop:?string]:?any;
          }

          const?getVegetables?=?({?color,?type?}:?Vegetables)?=>?{
          ??return?`A?${color???color?+?"?"?:?""}${type}`;
          };

          getVegetables({
          ??color:?"red",
          ??type:?"tomato",
          ??size:?12,
          ??price:?1.2
          });

          三、接口使用

          1. 定義函數(shù)類型

          在前面函數(shù)類型篇我們說了,可以使用接口來(lái)定義函數(shù)類型:

          interface?AddFunc?{
          ??(num1:?number,?num2:?number):?number;
          }

          這里定義了一個(gè)AddFunc結(jié)構(gòu),這個(gè)結(jié)構(gòu)要求實(shí)現(xiàn)這個(gè)結(jié)構(gòu)的值,必須包含一個(gè)和結(jié)構(gòu)里定義的函數(shù)一樣參數(shù)、一樣返回值的方法,或者這個(gè)值就是符合這個(gè)函數(shù)要求的函數(shù)。把花括號(hào)里包著的內(nèi)容稱為調(diào)用簽名,它由帶有參數(shù)類型的參數(shù)列表和返回值類型組成:

          const?add:?AddFunc?=?(n1,?n2)?=>?n1?+?n2;
          const?join:?AddFunc?=?(n1,?n2)?=>?`${n1}?${n2}`;?//?不能將類型'string'分配給類型'number'
          add("a",?2);?//?類型'string'的參數(shù)不能賦給類型'number'的參數(shù)

          上面定義的add函數(shù)接收兩個(gè)數(shù)值類型的參數(shù),返回的結(jié)果也是數(shù)值類型,所以沒有問題。而join函數(shù)參數(shù)類型沒錯(cuò),但是返回的是字符串,所以會(huì)報(bào)錯(cuò)。而當(dāng)調(diào)用add函數(shù)時(shí),傳入的參數(shù)如果和接口定義的類型不一致,也會(huì)報(bào)錯(cuò)。在實(shí)際定義函數(shù)的時(shí)候,名字是無(wú)需和接口中參數(shù)名相同的,只需要位置對(duì)應(yīng)即可。

          實(shí)際上,很少使用接口類型來(lái)定義函數(shù)類型,更多使用內(nèi)聯(lián)類型或類型別名配合箭頭函數(shù)語(yǔ)法來(lái)定義函數(shù)類型:

          type?AddFunc?=?(num1:?number,?num2:?number)?=>?number;


          這里給箭頭函數(shù)類型指定了一個(gè)別名 AddFunc,在其他地方就可以直接復(fù)用 AddFunc,而不用重新聲明新的箭頭函數(shù)類型定義。

          2. 定義索引類型

          在實(shí)際工作中,使用接口類型較多的地方是對(duì)象,比如 React 組件的 Props & State等,這些對(duì)象有一個(gè)共性,即所有的屬性名、方法名都是確定的。

          實(shí)際上,經(jīng)常會(huì)把對(duì)象當(dāng) Map 映射使用,比如下邊代碼中定義了索引是任意數(shù)字的對(duì)象 role1 和索引是任意字符串的對(duì)象 role2。

          const?role1?=?{
          ??0:?"super_admin",
          ??1:?"admin"
          };
          const?role2?=?{
          ??s:?"super_admin",??
          ??a:?"admin"
          };

          這時(shí)需要使用索引簽名來(lái)定義上邊提到的對(duì)象映射結(jié)構(gòu),并通過 “[索引名: 類型]”的格式約束索引的類型。索引名稱的類型分為 string 和 number 兩種,通過如下定義的 RoleDic 和 RoleDic1 兩個(gè)接口,可以用來(lái)描述索引是任意數(shù)字或任意字符串的對(duì)象:

          interface?RoleDic?{
          ??[id:?number]:?string;
          }

          interface?RoleDic1?{
          ??[id:?string]:?string;
          }

          const?role1:?RoleDic?=?{
          ??0:?"super_admin",
          ??1:?"admin"
          };

          const?role2:?RoleDic?=?{
          ??s:?"super_admin",??// error 不能將類型"{ s: string; a: string;?}"分配給類型"RoleDic"。
          ??a:?"admin"
          };

          const?role3:?RoleDic?=?["super_admin",?"admin"];

          需要注意,當(dāng)使用數(shù)字作為對(duì)象索引時(shí),它的類型既可以與數(shù)字兼容,也可以與字符串兼容,這與 JavaScript 的行為一致。因此,使用 0 或 '0' 索引對(duì)象時(shí),這兩者等價(jià)。

          上面的 role3 定義了一個(gè)數(shù)組,索引為數(shù)值類型,值為字符串類型。我們還可以給索引設(shè)置readonly,從而防止索引返回值被修改:

          interface?RoleDic?{
          ??readonly?[id:?number]:?string;
          }

          const?role:?RoleDic?=?{
          ??0:?"super_admin"
          };

          role[0]?=?"admin";?//?error?類型"RoleDic"中的索引簽名僅允許讀取

          注意,可以設(shè)置索引類型為 number。但是這樣如果將屬性名設(shè)置為字符串類型,則會(huì)報(bào)錯(cuò);但是如果設(shè)置索引類型為字符串類型,那么即便屬性名設(shè)置的是數(shù)值類型,也沒問題。因?yàn)?JS 在訪問屬性值時(shí),如果屬性名是數(shù)值類型,會(huì)先將數(shù)值類型轉(zhuǎn)為字符串,然后再去訪問:

          const?obj?=?{
          ??123:?"a",?
          ??"123":?"b"?//?報(bào)錯(cuò):標(biāo)識(shí)符“"123"”重復(fù)。
          };
          console.log(obj);?//?{?'123':?'b'?}

          如果數(shù)值類型的屬性名不會(huì)轉(zhuǎn)為字符串類型,那么這里數(shù)值123和字符串123是不同的兩個(gè)值,則最后對(duì)象obj應(yīng)該同時(shí)有這兩個(gè)屬性;但是實(shí)際打印出來(lái)的obj只有一個(gè)屬性,屬性名為字符串"123",值為"b",說明數(shù)值類型屬性名123被覆蓋掉了,就是因?yàn)樗晦D(zhuǎn)為了字符串類型屬性名"123";又因?yàn)橐粋€(gè)對(duì)象中多個(gè)相同屬性名的屬性,定義在后面的會(huì)覆蓋前面的,所以結(jié)果就是obj只保留了后面定義的屬性值。

          四、高級(jí)用法

          1. 繼承接口

          在 TypeScript 中,接口是可以繼承,這和ES6中的類一樣,這提高了接口的可復(fù)用性。來(lái)看一個(gè)場(chǎng)景:定義一個(gè)Vegetables接口,它會(huì)對(duì)color屬性進(jìn)行限制。再定義兩個(gè)接口TomatoCarrot,這兩個(gè)類都需要對(duì)color進(jìn)行限制,而各自又有各自獨(dú)有的屬性限制,可以這樣定義:

          interface?Vegetables?{
          ??color:?string;
          }

          interface?Tomato?{
          ??color:?string;
          ??radius:?number;
          }

          interface?Carrot?{
          ??color:?string;
          ??length:?number;
          }

          三個(gè)接口中都有對(duì)color的定義,但是這樣寫很繁瑣,可以用繼承來(lái)改寫:

          interface?Vegetables?{
          ??color:?string;
          }

          interface?Tomato?extends?Vegetables?{
          ??radius:?number;
          }

          interface?Carrot?extends?Vegetables?{
          ??length:?number;
          }

          const?tomato:?Tomato?=?{
          ??radius:?1.2?//?error??Property?'color'?is?missing?in?type?'{?radius:?number;?}'
          };

          const?carrot:?Carrot?=?{
          ??color:?"orange",
          ??length:?20
          };

          上面定義的?tomato?變量因?yàn)槿鄙倭藦?code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;max-width: 100%;overflow-wrap: break-word;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);box-sizing: border-box !important;">Vegetables接口繼承來(lái)的?color?屬性,所以報(bào)錯(cuò)了。

          一個(gè)接口可以被多個(gè)接口繼承,同樣,一個(gè)接口也可以繼承多個(gè)接口,多個(gè)接口用逗號(hào)隔開。比如再定義一個(gè)Food接口,Tomato?也可以繼承?Food

          interface?Vegetables?{
          ??color:?string;
          }

          interface?Food?{
          ??type:?string;
          }

          interface?Tomato?extends?Food,?Vegetables?{
          ??radius:?number;
          }

          const?tomato:?Tomato?=?{
          ??type:?"vegetables",
          ??color:?"red",
          ??radius:?1
          };??

          如果想要覆蓋掉繼承的屬性,那就只能使用兼容的類型進(jìn)行覆蓋:

          interface?Tomato?extends?Vegetables?{
          ??color:?number;
          }

          這里我們將color屬性進(jìn)行了覆蓋,并將其類型設(shè)置為了number類型,這時(shí)就會(huì)報(bào)錯(cuò),因?yàn)門omato 和 Vegetables 中的name屬性是不兼容的。

          2. 混合類型接口

          在 JavaScript 中,函數(shù)是對(duì)象類型。對(duì)象可以有屬性,所以有時(shí)一個(gè)對(duì)象既是一個(gè)函數(shù),也包含一些屬性。比如要實(shí)現(xiàn)一個(gè)計(jì)數(shù)器函數(shù),比較直接的做法是定義一個(gè)函數(shù)和一個(gè)全局變量:

          let?count?=?0;
          const?counter?=?()?=>?count++;

          但是這種方法需要在函數(shù)外面定義一個(gè)變量,更優(yōu)一點(diǎn)的方法是使用閉包:

          const?counter?=?(()?=>?{
          ??let?count?=?0;
          ??return?()?=>?{
          ????return?count++;
          ??};
          }
          )();
          console.log(counter());?//?1
          console.log(counter());?//?2

          TypeScript 支持直接給函數(shù)添加屬性,這在 JavaScript 中是支持的:

          let?counter?=?()?=>?{
          ??return?counter.count++;
          };
          counter.count?=?0;
          console.log(counter());?//?1
          console.log(counter());?//?2

          這里把一個(gè)函數(shù)賦值給countUp,又給它綁定了一個(gè)屬性count,計(jì)數(shù)保存在這個(gè)?count?屬性中。

          可以使用混合類型接口來(lái)指定上面例子中?counter?的類型:

          interface?Counter?{
          ??():?void;?
          ??count:?number;?
          }

          const?getCounter?=?():?Counter?=>?{?
          ??const?c?=?()?=>?{?
          ????c.count++;
          ??};
          ??c.count?=?0;?
          ??return?c;?
          };
          const?counter:?Counter?=?getCounter();?
          counter();
          console.log(counter.count);?//?1
          counter();
          console.log(counter.count);?//?2

          這里定義了一個(gè)Counter接口,這個(gè)結(jié)構(gòu)必須包含一個(gè)函數(shù),函數(shù)的要求是無(wú)參數(shù),返回值為void,即無(wú)返回值。而且這個(gè)結(jié)構(gòu)還必須包含一個(gè)名為count、值的類型為number類型的屬性。最后,通過getCounter函數(shù)得到這個(gè)計(jì)數(shù)器。這里?getCounter?的類型為Counter,它是一個(gè)函數(shù),無(wú)返回值,即返回值類型為void,它還包含一個(gè)屬性count,屬性返回值類型為number

          五、類型別名

          類型別名并不屬于接口類型的內(nèi)容,但是它和接口功能類似,所以這里放在一起來(lái)說。

          1. 基本使用

          接口類型的作用就是將內(nèi)聯(lián)類型抽離出來(lái),從而實(shí)現(xiàn)類型復(fù)用。其實(shí),還可以使用類型別名接收抽離出來(lái)的內(nèi)聯(lián)類型實(shí)現(xiàn)復(fù)用。可以通過如下所示“type 別名名字 = 類型定義”的格式來(lái)定義類型別名,比如上面定義的計(jì)數(shù)器方法的類型:

          type?Counter?=?{
          ??():?void;?
          ??count:?number;?
          }

          這樣寫看起來(lái)就像是在JavaScript中定義變量,只不過是把var、let、const換成了type。實(shí)際上,類型別名可以在接口類型無(wú)法覆蓋的場(chǎng)景中使用,比如聯(lián)合類型、交叉類型等:

          //?聯(lián)合類型
          type?Name?=?number?|?string;

          //?交叉類型
          type?Vegetables?=?{color:?string,?radius:?number}?&?{color:?string,?length:?number}

          這里定義了一個(gè) Vegetables 類型別名,表示兩個(gè)匿名接口類型交叉出的類型。

          需要注意:類型別名只是給類型取了一個(gè)別名,并不是創(chuàng)建了一個(gè)新的類型。

          2. 與接口區(qū)別

          通過上面的介紹,可以發(fā)現(xiàn)多數(shù)情況下是可以使用類型別名來(lái)替代的,那這是否說明這兩者是等價(jià)的呢?答案肯定是否定的,不然也不會(huì)出這兩個(gè)概念。在某些特定的場(chǎng)景下,這兩者還是存在很大區(qū)別。比如,重復(fù)定義的接口類型,它的屬性會(huì)疊加,這個(gè)特性使得我們可以很方便地對(duì)全局變量、第三方庫(kù)的類型做擴(kuò)展:

          interface?Vegetables?{
          ??color:?string;
          }

          interface?Vegetables?{
          ??radius:?number;
          }

          interface?Vegetables?{
          ??length:?number;
          }

          let?vegetables:?Vegetables?=?{
          ?color:??"red",
          ??radius:?2,
          ??length:?10
          }

          這里我們定義了三次 Vegetables 接口,此時(shí)可以賦值給變一個(gè)包含color、radius、length的對(duì)象,并且不會(huì)報(bào)錯(cuò)。

          如果重復(fù)定義類型別名:

          type?Vegetables?=?{
          ??color:?string;
          }

          type?Vegetables?=?{
          ??radius:?number;
          }

          type?Vegetables?=?{
          ??length:?number;
          }

          let?vegetables:?Vegetables?=?{
          ?color:??"red",
          ??radius:?2,
          ??length:?10
          }

          上述代碼就會(huì)報(bào)錯(cuò):'Vegetables' is already defined。所以,接口類型是可重復(fù)定義且屬性會(huì)疊加的,而類型別名是不可重復(fù)定義的。



          很感謝小伙伴看到最后??,如果您覺得這篇文章有幫助到您的的話不妨關(guān)注?+點(diǎn)贊??+收藏??+評(píng)論??,您的支持就是我更新的最大動(dòng)力。

          歡迎加入前端獵手技術(shù)交流群??,文末掃碼加我微信,我拉你進(jìn)群,一起交流技術(shù)以及代碼之外的一切???♀?

          瀏覽 92
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  欧美Aa欧美色 | 天堂五月丁香 | 小嫩苞一区二区三区 | 成人夜视频| 九九九,三级片 |