TypeScript中type和interface的區(qū)別及注意事項
前言
在 TS 中,type
和 interface
相似,都可以給類型命名并通過該名字來引用表示的類型。不過它們之間是存在一些差別的,我們在使用時也需要注意一些特殊場景。
概念
type
type
關鍵字是聲明類型別名的關鍵字。它的語法如下:
type AliasName = Type;
- type:聲明類型別名的關鍵字
- AliasName:類型別名的名稱
- Type:類型別名關聯(lián)的具體類型
interface
通過關鍵字 interface
可以定義一個接口類型。它能合并眾多類型聲明至一個類型聲明。
接口聲明只存在于編譯階段,在編譯后生成的 JS 代碼中不包含任何接口代碼。
語法如下:
interface InterfaceName { TypeMember; TypeMember; ... }
- interface:定義接口的關鍵字
- InterfaceName:接口名,首字母需要大寫
- TypeMember:接口的類型成員
異同點
不同點
- type 在聲明類型別名之后實際上是一個賦值操作,它需要將別名與類型關聯(lián)起來。也就是說類型別名不會創(chuàng)建出一種新的類型,它只是給已有類型命名并直接進行引用。interface是定義了一個接口類型。
- type 能夠表示非對象類型, 而 interface 則只能表示對象類型。
- interface可以繼承其他的接口、類等對象類型, type 不支持繼承。
好多文章里都說 type 也支持繼承,但是我認為這種說法不嚴謹。對于類型別名來說,它可以借助交叉類型來實現(xiàn)繼承的效果。而且這種方法也只適用于表示對象類型的類型別名,對于非對象類型是無法使用的。
type Shape = { name: string } type Circle = Shape & { radius: number } function foo(circle: Circle) { const name = circle.name const radius = circle.radius }
interface
接口名總是會直接顯示在編譯器的診斷信息和代碼編輯器的智能提示中,而 type 的名字只在特定情況下才會顯示出來——只有當類型別名表示數(shù)組類型、元組類型以及類或者接口的泛型實例類型時才展示。
type NumericType = number | bigint; interface Circle { radius: number; } function f(value: NumericType, circle: Circle) { const bar: boolean = value; // ~~~ // Type 'number | bigint' is not assignable to type 'boolean' // 這里沒有顯示類型別名 const baz: boolean = circle; // ~~~ // Type 'Circle' is not assignable to type 'boolean' }
- interface具有聲明合并的行為,而 type不會,這也意味著我們可以通過聲明合并的方式給 interface定義的類型進行屬性擴展。
- type可以通過 typeof來獲取實例的類型從而進行賦值操作
相同點
都可以用來定義 對象 或者 函數(shù) 的結(jié)構(gòu),而嚴謹?shù)膩碚f,type 是引用,而 interface是定義。
補充:Ts中type和interface定義類型擴展類型的方法
1、在Ts中,我們可以通過type和interface的方式去定義類型,一般情況下通過interface接口的方法定義的類型都可以通過type去定義。注意type要添加等號。Interface定義類型不需要添加等號。
下面代碼是用type聲明一個string類型的例子
type user=string //接收一個字符串類型的數(shù)據(jù),返回一個user類型(字符串類型)的數(shù)據(jù) function Input(str:string):user{ return str.slice(0,2) } //把返回結(jié)果賦值給userInput let userInput=Input('hello') //重新給其賦值一個字符串類型的值,沒有報錯,說明用type聲明的字符串類型生效 userInput='new'
下面代碼是用interface聲明一個對象類型的例子
interface Point{ x:number, y:number } //接收一個Point的對象類型數(shù)據(jù) function printCoord(pt:Point){ } //給函數(shù)傳一個對象類型的數(shù)據(jù),沒有報錯,說明用interface聲明的類型生效 printCoord({ x:100, y:100 })
2、 Interface擴展接口:可以在interface后面添加關鍵字extends去擴展接口。類型別名type需要使用&符號去擴展接口
下面代碼是用extends擴展接口的例子
//擴展接口 interface Animal{ name:string } interface Bear extends Animal{ honey:boolean } //聲明一個類型為Bear類型的對象,要求既要有name,也要有honey。說明用extends擴展接口成功 const bear:Bear={ name:'winie', honey:true } console.log(bear.name); console.log(bear.honey);
下面代碼是用type擴展接口的例子
//擴展類型 type Animal={ name:string } //給Animal擴展接口 type Bear=Animal&{ honey:boolean } const bear:Bear={ name:'winie', honey:true }
3、向現(xiàn)有類型添加新字段,interface可以通過定義同名的方式去擴展字段,類型別名type是不能通過同名的方式去進行擴展的。
下面代碼是interface通過定義同名的方式向現(xiàn)有類型添加新字段
//向現(xiàn)有的類型添加新字段 interface MyWindow{ title:string } interface MyWindow{ count:number } const w:MyWindow={ title:'wz', count:666 }
下面代碼會報錯,因為類型別名type是不能通過同名的方式去進行擴展的。
//類型創(chuàng)建后不能更改 type MyWindow={ title:string } type MyWindow={ }
總結(jié)
對于 type來說,更多的是對類型的一種復用,比如在項目中需要用到一些比較復雜的或者書寫起來很長的類型。我們可以使用 type來直接引用該類型:
type FType = boolean | string | number;
而對于 interface
來說,它是正兒八經(jīng)的用來定義接口類型(約束數(shù)類型和屬性)的,且接口類型是支持繼承和聲明合并的。
所以在對于對象結(jié)構(gòu)的類型定義上,建議盡可能的使用 interface
,而在合適的場景使用 type
。
到此這篇關于TypeScript中type和interface區(qū)別及注意事項的文章就介紹到這了,更多相關TS type和interface區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
原生JavaScript實現(xiàn)合并多個數(shù)組示例
這篇文章主要介紹了原生的JavaScript及jquery實現(xiàn)合并多個數(shù)組,很簡單,很實用,大家可以看看2014-09-09解析javascript圖片懶加載與預加載的分析總結(jié)
本篇文章介紹了javascript圖片懶加載與預加載的分析,詳細的介紹了懶加載和預加載的問題,有需要的可以了解一下。2016-10-10