它们都是"贴标签"
你可以把 TypeScript 的类型理解为给数据贴标签。一张纸上写了"姓名、年龄、电话",贴个标签叫「个人信息」——以后看到这个标签,就知道里面该有什么内容。
贴标签有两种方法:interface 和 type。大部分时候它们能互换,但各有一些对方做不到的事。
interface:专门用于定义对象的形状
interface Person {
id: number
name: string
age: number
}
const person: Person = {
id: 1,
name: 'John Doe',
age: 30,
}
这就是告诉 TypeScript:凡是标记为 Person 的变量,必须有 id、name、age 这三个字段,类型还得对上。
interface 有两个独家本领:
- 继承:可以用
extends在一个模板的基础上加字段,就像"学生"基于"人"再加上"学号"。 - 同名自动合并:如果你在两个地方写了同名 interface,TypeScript 会把它们合在一起。这个特性在给第三方库打补丁时特别好用。
type:可以为任何类型创建别名,包括基本类型、联合类型、元组等
type User = {
id: number
name: string
}
type UserList = User[] // 用户列表
// type UserList = Array<User>; 这样写也可以 !!!
// Type 可以定义任何类型
type ID = string | number; // 联合类型
type Point = [number, number]; // 元组
type 不光能描述对象,还能描述"要么是数字要么是字符串"这种组合、固定长度的元组等。interface 做不到这些。
但 type 不能自动合并,写两个同名的 type 会直接报错。
一张表看完区别
| interface | type | |
|---|---|---|
| 描述对象结构 | ✅ | ✅ |
| 同名自动合并 | ✅ | ❌ |
| 继承/扩展 | extends | & 符号 |
| 联合类型(是A或是B) | ❌ | ✅ |
| 元组(固定长度的数组) | ❌ | ✅ |
// 自动合并
interface Window {
title: string;
}
interface Window {
isMaximized: boolean;
}
// 结果:Window 同时拥有 title 和 isMaximized 属性
type User = { name: string };
// type User = { age: number }; // Error: Duplicate identifier 'User'.
// Interface 扩展
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
// Type 扩展
type AnimalType = {
name: string;
}
type BearType = AnimalType & {
honey: boolean;
}
// Type 可以定义任何类型
type ID = string | number; // 联合类型
type Point = [number, number]; // 元组
实际项目怎么写?
简单记一句话:默认用 interface,遇到它做不了的事再换 type。
// 描述一个对象 → 用 interface
export interface Product {
id: number
name: string
price: number
}
// 描述一组对象 → 用 type 更简洁
export type ProductList = Product[]
记住两件事
- TypeScript 的类型只在写代码时帮你检查错误,代码跑起来之后类型就消失了。所以你不能在运行时用
typeof来判断一个 interface 或 type。 - 不确定用哪个的时候,先写 interface。哪天发现 interface 不够灵活了,再改成 type。
评论区