Todo 原來是 interface上一篇使用 type 描述一筆 Todo 資料:
type Todo = {
id: number
text: string
completed: boolean
}
不過實際打開目前專案的 types.ts,看到的是:
export interface Todo {
id: number
text: string
completed: boolean
}
原本才剛理解 type,現在又出現了 interface,而且兩種寫法看起來很像。
interface 也是 TypeScript 描述資料結構的方式。上面的程式表示,一筆 Todo 必須包含:
number 的 id
string 的 text
boolean 的 completed
所以在這個例子中,不論使用 type 還是 interface,都可以描述相同的 Todo 物件。
interface除了 Todo,目前專案也使用 interface 描述 Component 接收的 Props。
例如 TodoItem.tsx:
interface TodoItemProps {
todo: Todo
onToggle: (id: number) => void
onDelete: (id: number) => void
}
這段程式表示 TodoItem 需要接收三個 Props:
todo:一筆符合 Todo 格式的資料onToggle:接收數字的函式onDelete:接收數字的函式其中:
(id: number) => void
是在描述函式型別。這個函式接收一個型別為 number 的 id,而 void 可以先理解成呼叫函式後,不需要使用它的回傳結果。
接著,TodoItemProps 會用來檢查傳入 Component 的資料:
function TodoItem({
todo,
onToggle,
onDelete,
}: TodoItemProps) {
// ...
}
另外,interface 並不是 React 的語法,React 也沒有規定 Props 一定要使用它。這只是目前專案選擇使用 TypeScript 的 interface 描述 Props。
type 也可以嗎?目前的 TodoItemProps 也可以改成:
type TodoItemProps = {
todo: Todo
onToggle: (id: number) => void
onDelete: (id: number) => void
}
在這個使用情境中,兩種寫法都可以正常進行型別檢查。
看到用來描述簡單物件或 Props 的型別時,不需要認為其中一種才是正確答案。很多時候,type 和 interface 都能完成相同的工作。
type 能描述的範圍比較廣雖然兩者都能描述物件,但 type 還能替其他種類的型別取名。
例如上一篇出現的:
type TodoId = number
type TodoStatus = 'all' | 'active' | 'completed'
第一行替 number 取了一個別名,第二行則使用 Union Type 列出幾種可能的值。
interface 主要用來描述物件結構,不能直接用來替 number 或一組 Union Type 取名。
可以先簡單區分:
type:可以替基本型別、Union Type、物件型別等內容取名interface:主要用來描述物件應該有哪些成員假設已經有一個 Todo,現在想建立包含建立時間的 TimedTodo。interface 可以使用 extends:
interface TimedTodo extends Todo {
createdAt: number
}
type 則可以使用 & 組合型別:
type TimedTodo = Todo & {
createdAt: number
}
兩種寫法都會保留原本 Todo 的內容,再加入 createdAt。
目前可以先記成:
interface 通常使用 extends 擴充type 通常使用 & 組合interface 可以進行宣告合併interface 還有一項特性:如果同一個名稱被宣告多次,TypeScript 會嘗試將內容合併。
interface Todo {
id: number
}
interface Todo {
text: string
}
合併後,Todo 會同時需要 id 和 text。
type 則不能使用相同名稱重複宣告,否則會出現名稱重複的錯誤。
這項功能稱為 Declaration Merging,也就是「宣告合併」。目前的 Todo List 不一定需要使用它,先知道這是兩者的一項差異即可。
TypeScript 官方文件:Type Aliases 與 Interfaces 的差異
type 和 interface 蠻相似的,很多情況下都可以自由選擇。
目前可以根據需求簡單判斷:
type
interface
重點不是每次都要選出比較厲害的那一個,而是讓型別能清楚描述資料,並維持專案寫法一致。
interface 是 TypeScript 描述物件結構的方式type 或 interface
interface
type 還能替基本型別與 Union Type 取名interface 可以使用 extends 擴充,type 可以使用 & 組合interface 可以進行宣告合併,type 則不能重複宣告剛看到 interface 時,會覺得怎麼又多出一種描述物件的語法。實際比較後才知道,它和 type 在很多情況下都能完成相同的工作,只是能描述的範圍與擴充方式有些不同。至少現在再看到專案裡用 interface 描述的 Props,不會只覺得它們又是一串陌生的型別了。
下篇見!