Typescript中 type 與 interface 的區(qū)別說明總結(jié)
Typescript類型別名 type
類型別名用來給一個(gè)類型起個(gè)新名字,使用 type 創(chuàng)建類型別名,類型別名不僅可以用來表示基本類型,還可以用來表示對象類型、聯(lián)合類型、元組和交集
// 基本類型 type userName = string; // 聯(lián)合類型 type userId = string | number; // 數(shù)組類型 type arr = number[]; // 對象類型 type Person = { id: userId; // 可以使用定義類型 name: userName; age: number; gender: string; isWebDev: boolean; }; // 范型 type Tree<T> = { value: T }; const user: Person = { id: "901", name: "椿", age: 22, gender: "女", isWebDev: false, }; const numbers: arr = [1, 8, 9];
Typescript接口 interface
接口是命名數(shù)據(jù)結(jié)構(gòu)(例如對象)的另一種方式;與type 不同,interface僅限于描述對象類型,接口的聲明語法也不同于類型別名的聲明語法。
interface Person { id: userId; name: userName; age: number; gender: string; isWebDev: boolean; }
語法不同
interface Point { x: number; y: number; } interface SetPoint { (x: number, y: number): void } type Point = { x: number y: number } type SetPoint = (x: number, y: number) => void
擴(kuò)展 (繼承)不同
擴(kuò)展 (繼承) 語法:interface 使用 extends,type 使用 &
// extends方式不同 interface PartialPointX { x: number } interface Point extends PartialPointX { y: number } type PartialPointX = { x: number } // & 交叉類型 type Point = PartialPointX & { y: number }
兩者也可以互相繼承
// interface 繼承 type type Person{ name:string } interface Student extends Person { stuNo: number } // type 繼承 interface interface Person{ name:string } type Student = Person & { stuNo: number }
同名合并
interface 支持,type 不支持(如果系統(tǒng)中存在兩個(gè)使用 interface 定義的接口且同名的話,系統(tǒng)則會自動(dòng)合并它們),如果存在兩個(gè)同名 type 則會報(bào)錯(cuò)
// interface可以定義多次,并將被視為單個(gè)接口 // These two declarations become: // interface Point { x: number; y: number } interface Point { x: number } interface Point { y: number }
描述類型
對象、函數(shù)兩者都適用,但是 type 可以用于基礎(chǔ)類型描述、聯(lián)合類型、元組(簡單類型用 type 來定義)
type test = number //基本類型 let num: test = 10 type userOjb = { name:string } // 對象 type getName = () => string // 函數(shù) type data = [number, string] // 元組 type numOrFun = userOjb | getName // 聯(lián)合類型 interface Common { name: string } interface Person<T> extends Common { age: T sex: string } type People<T> = { age: T sex: string } & Common // 聯(lián)合類型 type P1 = Person<number> | People<number> // 元組 type P2 = [Person<number>, People<number>]
映射類型
type 支持計(jì)算屬性,生成映射類型,interface 不支持
場景: 有時(shí)候一個(gè)類型需要基于另外一個(gè)類型,但是你又不想拷貝一份,這個(gè)時(shí)候你可以考慮使用映射類型
// keys 聯(lián)合類型 type Keys = 'firstName' | 'surName' // DudeType 會遍歷 keys 所有屬性,然后設(shè)置為 string 類型 type DudeType = { [key in Keys]: string } const test: DudeType = { firstName:'Paerl' surName:'Grz' } // 報(bào)錯(cuò) //interface DudeType2 { // [key in keys]: string //} // 帶泛型的映射類型 // 在這個(gè)例子中,OptionsFlags 會遍歷 Type 所有的屬性,然后設(shè)置為布爾類型 type OptionsFlags<Type> = { [Property in keyof Type]: boolean }; type FeatureFlags = { darkMode: () => void newUserProfile: () => void }; type FeatureOptions = OptionsFlags<FeatureFlags> // type FeatureOptions = { // darkMode: boolean // newUserProfile: boolean // }
interface 可以被 class 實(shí)現(xiàn)
interface 和 type 都可以實(shí)現(xiàn)一個(gè)函數(shù)的類型,但是 interface 可以被 類class
實(shí)現(xiàn)(implements),type 不行
interface SetPerson { (age: number, sex: string): void } type SetPeople = (age: number, sex: string) => void let setPerson: SetPerson = function (age, sex) {} let setPeople: SetPeople = function (age, sex) {} class Config implements SetPerson { setPerson(age: number, sex: string) { // do nothing } }
type 可以配合 typeof
type 可以結(jié)合 typeof
使用,interface 不行
class Config { setPerson(age: number, sex: string) { // do nothing } } // 獲取 Config class 的類型 type T = typeof Config const C: T = class { setPerson(age: number, sex: string) { // do nothing } }
總結(jié)
雖然 官方 中說幾乎接口的所有特性都可以通過類型別名來實(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)不出來,還是會認(rèn)為是不同基本類型的組合。
接口之間的類型關(guān)系會被緩存,而交叉類型會被看成組合起來的一個(gè)整體。
最后一個(gè)值得注意的區(qū)別是,在檢查到目標(biāo)類型之前會先檢查每一個(gè)組分。
出于這個(gè)原因,建議使用 接口/擴(kuò)展interface/extends
擴(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; } // interface SisterAn // 接口“SisterAn”錯(cuò)誤擴(kuò)展接口“Sister”。 // 屬性“sex”的類型不兼容。 // 不能將類型“string”分配給類型“number”。ts(2430) // “SisterAn”已聲明,但從未使用過。ts(6196) // 交叉類型 type Sister1 = { sex: number; } type Sister2 = { sex: string; } type SisterAn = Sister1 & Sister2; // 不報(bào)錯(cuò),此時(shí)的 SisterAn 是一個(gè)'number & string'類型,也就是 never
到此這篇關(guān)于Typescript中 type 與 interface 的區(qū)別的文章就介紹到這了,更多相關(guān)Typescript中 type 與 interface 的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JavaScript實(shí)現(xiàn)繼承機(jī)制之構(gòu)造函數(shù)方法對象冒充的使用詳解
我們知道JavaScript是面向?qū)ο蟮哪_本語言,那么既然是面向?qū)ο?,繼承一定是必不可少的了。JavaScript的核心是ECMAScript,JavaScript繼承機(jī)制的實(shí)現(xiàn)其實(shí)就是ECMAScript繼承機(jī)制的實(shí)現(xiàn)2013-05-05在JavaScript中處理時(shí)間之getHours()方法的使用
這篇文章主要介紹了在JavaScript中處理時(shí)間之getHours()方法的使用,是JS入門學(xué)些中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06在JavaScript中操作時(shí)間之getUTCDate()方法的使用
這篇文章主要介紹了在JavaScript中操作時(shí)間之getUTCDate()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06jquery下組織javascript代碼(js函數(shù)化)
這里整理的是jquery下js的一些代碼組織方法,大家可以借鑒下整理出基于jquery的自己喜歡的模式。2010-08-08用JavaScript腳本實(shí)現(xiàn)Web頁面信息交互
這篇文章主要給大家介紹了關(guān)于用JavaScript腳本實(shí)現(xiàn)Web頁面信息交互的相關(guān)資料,需要的朋友可以參考下2006-12-12