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)則會自動合并它們),如果存在兩個(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)文章希望大家以后多多支持腳本之家!
- 詳解TypeScript中type與interface的區(qū)別
- typeScript?核心基礎(chǔ)之接口interface
- typescript中type和interface的區(qū)別有哪些
- Typescript中interface自動化生成API文檔詳解
- TypeScript中的interface與type實(shí)戰(zhàn)
- TypeScript中type和interface的區(qū)別及注意事項(xiàng)
- Vue 3 TypeScript 接口Interface使用示例詳解
- TypeScript接口interface的高級用法詳解
- 解讀Typescript中interface和type的用法及區(qū)別
- TypeScript中type與interface的使用和區(qū)別
相關(guān)文章
JavaScript中的call方法和apply方法使用對比
這篇文章主要介紹了JavaScript中的call方法和apply方法使用對比,需要的朋友可以參考下2015-08-08
JavaScript字符串對象charAt方法入門實(shí)例(用于取得指定位置的字符)
這篇文章主要介紹了JavaScript字符串對象charAt方法入門實(shí)例,charAt方法用于取得指定位置的字符,需要的朋友可以參考下2014-10-10
DOM下的節(jié)點(diǎn)屬性和操作小結(jié)
DOM 節(jié)點(diǎn)屬性操作方法小結(jié)。2009-05-05

