成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

type 與 interface 的區別,你真的懂了嗎?

開發 前端
在寫 ts 相關代碼的過程中,總能看到 interface 和 type 的身影。它們的作用好像都一樣的,相同的功能用哪一個都可以實現,也都很好用,所以也很少去真正的理解它們之間到底有啥區別, 分別在什么場景下使用,將自己學習的內容記錄分享一下。

類型別名 type

首先認識一下什么是類型別名?

類型別名用來給一個類型起個新名字,使用 type 創建類型別名,類型別名不僅可以用來表示基本類型,還可以用來表示對象類型、聯合類型、元組和交集。讓我們看一些例子:

type userName = string; // 基本類型
type userId = string | number; // 聯合類型
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];

接口 interface

接口是命名數據結構(例如對象)的另一種方式;與type 不同,interface僅限于描述對象類型。

接口的聲明語法也不同于類型別名的聲明語法。讓我們將上面的類型別名 Person 重寫為接口聲明:

interface Person {
id: userId;
name: userName;
age: number;
gender: string;
isWebDev: boolean;
}

interface和type的相似之處

在討論二者區別之前, 首先看一下二者的相似之處(為何開發中,我們覺得用哪個都一樣)

都可以描述 Object和Function

兩者都可以用來描述對象或函數,但語法不同:

Type

type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;

Interface

interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}

二者都可以被繼承

interface 和 type 都可以繼承。

另一個值得注意的是,接口和類型別名并不互斥。類型別名可以繼承接口,反之亦然。只是在實現形式上,稍微有些差別。

interface 繼承 interface

interface Person{
name:string
}
interface Student extends Person { stuNo: number }

interface 繼承 type

type Person{
name:string
}
interface Student extends Person { stuNo: number }

type 繼承 type

type Person{
name:string
}
type Student = Person & { stuNo: number }

type 繼承 interface

interface Person{
name:string
}
type Student = Person & { stuNo: number }

實現 implements

類可以實現interface 以及 type(除聯合類型外)

interface ICat{
setName(name:string): void;
}
class Cat implements ICat{
setName(name:string):void{
// todo
}
}
// type
type ICat = {
setName(name:string): void;
}
class Cat implements ICat{
setName(name:string):void{
// todo
}
}

上面提到了特殊情況,類無法實現聯合類型, 是什么意思呢?

type Person = { name: string; } | { setName(name:string): void };
// 無法對聯合類型Person進行實現
// error: A class can only implement an object type or intersection of object types with statically known members.
class Student implements Person {
name= "張三";
setName(name:string):void{
// todo
}
}

上面聊了interface與 type的相似之處, 接下來就來看看他們的區別。

二者區別

1. 定義基本類型別名

type可以定義基本類型別名, 但是interface無法定義,如:

type userName = string
type stuNo = number
...

2. 聲明聯合類型

type可以聲明聯合類型, 例如:

type Student = {stuNo: number} | {classId: number}

3. 聲明元組

type可以聲明 元組類型:

type Data = [number, string];

以上都是 type能做到, 而interface做不到的, 接下來聊聊type做不到的

4. 聲明合并

如果你多次聲明一個同名的接口,TypeScript 會將它們合并到一個聲明中,并將它們視為一個接口。這稱為聲明合并, 例如:

interface Person { name: string }
interface Person { age: number }
let user: Person = {
name: "Tolu",
age: 0,
};

這種情況下,如果是type的話,重復使用Person是會報錯的:

type Person { name: string };  
// Error: 標識符“Person”重復。ts(2300)
type Person { age: number }

5. 索引簽名問題

如果你經常使用TypeScript, 一定遇到過相似的錯誤:

Type 'xxx' is not assignable to type 'yyy'

Index signature is missing in type 'xxx'.

看個例子來理解問題:

interface propType{
[key: string] : string
}
let props: propType
type dataType = {
title: string
}
interface dataType1 {
title: string
}
const data: dataType = {title: "訂單頁面"}
const data1: dataType1 = {title: "訂單頁面"}
props = data
// Error:類型“dataType1”不可分配給類型“propType”; 類型“dataType1”中缺少索引簽名
props = data1

我們發現dataType和dataType1對應的類型一樣,但是interface定義的就賦值失敗,是什么原因呢?剛開始百思不解,最后我在 stack overflow上找到了一個相似的問題:

并且很幸運的找到了有效的答案:

翻譯過來的大致意思就是:

Record<string,string>與{[key:string]:string}相同。只有當該類型的所有屬性都已知并且可以對照該索引簽名進行檢查時,才允許將子集分配給該索引簽名類型。在您的例子中,從exampleType到Record<string,string>的所有內容都是可分配的。這只能針對對象字面量類型進行檢查,因為一旦聲明了對象字面量類型,就無法更改它們。因此,索引簽名是已知的。

相反,在你使用interface去聲明變量時,它們在那一刻類型并不是最終的類型。由于interfac可以進行聲明合并,所以總有可能將新成員添加到同一個interface定義的類型上。

再結合??第4點 聲明合并的講解, 這樣就很好理解了。就是說interface定義的類型是不確定的, 后面再來一個:

interface propType{
title:number
}

這樣propType類型就被改變了。

總結

官方推薦用 interface,其他無法滿足需求的情況下用 type。

但其實,因為 聯合類型 和 交叉類型 是很常用的,所以避免不了大量使用 type 的場景,一些復雜類型也需要通過組裝后形成類型別名來使用。

所以,如果想保持代碼統一,還是可選擇使用 type。通過上面的對比,類型別名 其實可涵蓋 interface 的大部分場景。

對于 React 組件中 props及 state,使用 type ,這樣能夠保證使用組件的地方不能隨意在上面添加屬性。如果有自定義需求,可通過 HOC二次封裝。

編寫三方庫時使用interface,其更加靈活自動的類型合并可應對未知的復雜使用場景。

參考資料:

  • TypeScript: type alias 與 interface
責任編輯:龐桂玉 來源: 前端大全
相關推薦

2022-05-06 09:21:21

TypeScriptinterfacetype

2013-12-26 09:44:30

互聯網物聯網區別

2023-10-27 07:39:44

IOC容器Spring

2022-03-08 15:01:48

負載均衡IP服務器

2022-07-27 08:01:29

CMS垃圾回收器

2021-10-10 20:36:49

Android Root權限

2021-10-12 10:50:31

鴻蒙HarmonyOS應用

2024-12-04 09:41:06

2024-03-05 18:19:07

localhostLinux數據庫

2013-07-15 16:55:45

2011-06-14 12:56:55

SQL Server復災

2024-04-07 08:23:01

JS隔離JavaScript

2022-11-28 07:10:57

2024-08-12 15:23:43

LangChain

2022-06-07 08:14:35

PGPAGETUPLE

2021-08-05 08:32:45

TypeScript InterfaceType

2022-03-13 18:53:31

interfacetypeTypeScript

2022-01-06 07:59:32

WebGPUOpenGL引擎

2022-06-06 07:58:52

勒索軟件惡意軟件解密

2022-10-08 00:00:00

DNS地址網關
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天操夜夜爽 | 九九久久精品 | 精品亚洲一区二区三区 | 成年视频在线观看福利资源 | 国产日韩精品视频 | 久久精品欧美一区二区三区不卡 | 免费大黄视频 | 精品久久久久久亚洲综合网站 | 无码一区二区三区视频 | 岛国精品| 夜久久| 国产小u女发育末成年 | 午夜激情在线视频 | 中文字幕中文字幕 | 亚洲黄色av| 久久免费视频1 | 国产农村一级片 | 成人精品一区二区户外勾搭野战 | 国产成人精品免高潮在线观看 | 欧美九九九 | 影音先锋成人资源 | 一级高清视频 | cao视频| 欧美精品网 | 午夜亚洲 | 91社区在线高清 | 国产精品成人一区 | 国产精品污www一区二区三区 | 欧美大片一区 | 久久精品欧美一区二区三区不卡 | 日韩中文在线 | 亚洲+变态+欧美+另类+精品 | 亚洲国产偷 | 一级看片免费视频囗交动图 | 中文字幕一区二区三区四区五区 | 亚洲精品在线视频 | 成人av资源在线 | 中文字幕视频在线免费 | 亚洲伊人精品酒店 | 一级黄色淫片 | 久久精品视频一区二区三区 |