interface 和 type 有什么区别?
下文默认基于 TypeScript 5.x,并假设开启
strict: true。
面试速答(30 秒版 TL;DR)
interface和type都能描述“值的形状”,比如对象结构、函数签名。- 真正差别不在“谁更高级”,而在表达能力和扩展方式:
interface更适合描述对象契约、类实现、库的可扩展 API。type更适合做联合类型、交叉类型、条件类型、映射类型这类“类型计算”。
- 一个高频结论:
- 想表达“一个对象长什么样”,
interface通常更直观; - 想表达“把几个类型拼装、变换、过滤”,
type更合适。
- 想表达“一个对象长什么样”,
- 面试里不要答成“完全等价”。它们有重叠,但不完全重叠。
1. 先看共同点:都能描述对象和函数
interface UserByInterface {
id: number;
name: string;
}
type UserByType = {
id: number;
name: string;
};
interface FnByInterface {
(value: string): number;
}
type FnByType = (value: string) => number;
所以第一句话应该先说清楚:
- 在“描述普通对象结构”这件事上,它们大量重叠;
- 差异主要体现在“还能不能继续做更复杂的类型表达”。
2. 核心区别:type 能做类型运算,interface 更偏契约声明
2.1 type 可以直接表示联合、交叉、原始类型、元组
type Status = "idle" | "loading" | "success" | "error";
type Id = string | number;
type Pair = [string, number];
type WithTime = { createdAt: Date } & { updatedAt: Date };
这些写法 interface 做不到。
所以面试里一个很稳的答法是:
type不只是“对象别名”;- 它本质上是给任意类型表达式起名字。
2.2 interface 更强调“对象世界里的扩展和约束”
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}
class Husky implements Dog {
constructor(public name: string) {}
bark() {
console.log("wang");
}
}
这类“接口扩展 + 类实现”的语义,用 interface 可读性通常更强。
3. 一个非常高频的区别:声明合并
interface 支持 declaration merging,type 不支持。
interface RequestConfig {
url: string;
}
interface RequestConfig {
timeout?: number;
}
const config: RequestConfig = {
url: "/api/user",
timeout: 3000,
};
最终 RequestConfig 会被合并成:
{
url: string;
timeout?: number;
}
但下面这种写法会报错:
type RequestConfigType = {
url: string;
};
type RequestConfigType = {
timeout?: number;
};
这也是为什么:
- 写库类型声明;
- 扩展全局对象;
- 给第三方库做补充声明;
很多场景会优先看到 interface。
4. extends 和 & 看起来像,语义并不完全一样
4.1 interface extends
interface A {
name: string;
}
interface B extends A {
age: number;
}
更像“基于已有契约继续扩展”。
4.2 type 用交叉类型 &
type A = {
name: string;
};
type B = A & {
age: number;
};
更像“把多个类型结果组合起来”。
工程上常见区别是:
extends偏声明式、面向对象建模;&偏类型运算、组合式建模。
5. 什么时候优先用 interface
下面这些场景,interface 往往更自然:
- 定义组件
props、接口返回对象、领域模型对象; - 给 class 做
implements; - 需要声明合并;
- 希望团队把它理解成“可扩展的对象契约”。
示例:
interface ButtonProps {
type?: "primary" | "default";
disabled?: boolean;
onClick?: () => void;
}
6. 什么时候优先用 type
下面这些场景,type 基本更合适:
- 联合类型;
- 交叉类型;
- 条件类型;
- 映射类型;
- 元组;
- 给一个复杂类型表达式起别名。
type ApiState<T> =
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; message: string };
这类写法如果硬换成 interface,通常会很别扭。
7. 高频面试题标准答法
7.1 interface 能不能替代 type
不能完全替代。
因为 interface 不能直接表示:
- 联合类型;
- 条件类型;
- 元组;
- 原始类型别名。
7.2 type 能不能替代 interface
很多“对象结构描述”可以替代,但有两个常见缺口:
- 没有声明合并;
- 在“接口契约”语义上不如
interface直观。
7.3 团队里到底怎么选
比较稳的工程规则是:
- 对象契约优先
interface; - 类型运算优先
type; - 不要为了统一而牺牲表达力。
8. 常见误区
- 误区 1:认为
interface比type更“面向对象”,所以任何地方都该用它。- 事实是 TypeScript 的很多高级能力都建立在
type上。
- 事实是 TypeScript 的很多高级能力都建立在
- 误区 2:认为
type只是interface的别名。- 不对,
type的表达范围明显更大。
- 不对,
- 误区 3:把
extends和&当成完全等价。- 它们很多时候结果接近,但设计意图不同。
速记要点
interface侧重对象契约、扩展、实现、声明合并。type侧重类型表达式和类型运算。- 描述对象时两者有重叠;做联合、条件、映射时优先
type。