TS 面试必考题:type 与 interface 的 6 大核心区别,90% 的人答不全

在前端面试中,TypeScript 相关问题的占比逐年升高,而「type 和 interface 有什么区别」几乎是 TS 面试的第一道必考题。

很多同学只能说出 "一个用 extends 继承,一个用 & 合并" 这种表层答案,很容易被面试官追问到哑口无言。其实这两者的差异,本质上是设计理念的不同:interface 是 "契约式的接口定义",天生开放可扩展;type 是 "灵活的类型别名",主打全能与组合

本文就从语法特性、设计逻辑到实战选型,一次性讲透 type 与 interface 的共同点与核心区别,看完不仅能应付面试,还能在项目中用得更合理。

一、先搞懂:两者的共同点是什么?

很多人一上来就讲区别,其实先理清共同点,才能更好地理解两者的定位。

interfacetype 都是 TypeScript 中用来定义类型结构的核心语法,核心作用都是做类型约束,它们在基础场景下几乎可以互换:

1. 都可以描述对象结构

无论是普通对象还是带方法的对象,两者都能实现完全等价的约束效果:

typescript 复制代码
// interface 写法
interface User {
  id: number;
  name: string;
  sayHello(): void;
}

// type 写法
type User = {
  id: number;
  name: string;
  sayHello(): void;
};

2. 都可以定义函数类型

两者都能描述函数的参数和返回值类型,都可用于函数参数、返回值的类型注解:

typescript 复制代码
// interface 调用签名写法
interface AddFunc {
  (a: number, b: number): number;
}

// type 函数类型表达式写法
type AddFunc = (a: number, b: number) => number;

3. 都支持泛型、索引签名

两者都可以搭配泛型使用,也都支持索引签名来描述动态键的对象:

typescript 复制代码
// 泛型支持
interface Box<T> { value: T }
type Box<T> = { value: T };

// 索引签名
interface Dictionary { [key: string]: number }
type Dictionary = { [key: string]: number };

二、核心区别:6 个维度彻底分清

讲完共同点,我们来看最核心的差异,这也是面试的核心采分点。

1. 类型覆盖范围:type 全能,interface 仅支持对象

这是两者最基础的区别:interface 只能用来定义对象类型,而 type 可以定义任意类型

type 支持但 interface 做不到的场景:

  • 基本类型别名

    ini 复制代码
    // ✅ type 可以
    type UserId = string;
    type StatusCode = number;
    
    // ❌ interface 不支持,语法完全错误
    interface UserId = string;
  • 联合类型

    ini 复制代码
    // ✅ type 可以
    type Status = 'success' | 'error' | 'loading';
    type Result = User | null;
    
    // ❌ interface 无法原生表达联合类型
  • 元组类型

    typescript 复制代码
    // ✅ type 可以
    type DataTuple = [string, number, boolean];
    
    // ❌ interface 无法直接表达元组结构

简单总结:只要不是纯对象结构的类型,基本都要用 type 来定义。

2. 扩展继承:语法不同,行为也有差异

两者都支持类型扩展,但语法和底层处理逻辑完全不同:

  • interface 使用 extends 关键字继承
  • type 使用交叉类型 & 进行合并

基础示例

typescript 复制代码
// interface 继承
interface BaseUser { id: number }
interface Admin extends BaseUser { role: string }

// type 交叉合并
type BaseUser = { id: number };
type Admin = BaseUser & { role: string };

面试深水区:同名属性的处理逻辑不同

这是 90% 的人答不上来的细节点:

  • interface extends 时,如果父子接口同名属性类型不兼容,会直接报错,强制保证类型一致性:

    css 复制代码
    interface A { value: string }
    // ❌ 报错:Interface 'B' incorrectly extends interface 'A'
    interface B extends A { value: number }
  • type 交叉时,同名属性不会语法报错,而是会将类型合并为 never(因为 string & number 不存在合理类型):

    ini 复制代码
    type A = { value: string };
    type B = A & { value: number }; 
    // ✅ 语法不报错,但 value 的实际类型为 never

补充:两者可以互相扩展 ------interface 可以 extends 一个对象类型的 typetype 也可以通过 & 合并一个 interface

3. 声明合并:interface 天生支持,type 完全禁止

这是 interface 独有的核心特性,也是它不可替代的原因:同名的 interface 会自动进行声明合并 ,而 type 重复定义会直接报错。

kotlin 复制代码
// ✅ interface 声明合并
interface User { id: number }
interface User { name: string }

// 最终合并为 { id: number; name: string }
const user: User = { id: 1, name: '张三' }; // 正常使用
ini 复制代码
// ❌ type 重复声明直接报错
type User = { id: number };
type User = { name: string }; 
// 错误:Duplicate identifier 'User'

声明合并的核心使用场景:扩展第三方库的类型、给全局对象添加属性。比如给 Window 对象扩展自定义属性、给 Vue 实例扩展全局属性,都必须靠 interface 的声明合并来实现。

从设计理念上说,interface 是开放的,type 是封闭的------ 接口生来就是用来定义 "可扩展的契约",而类型别名只是给一个固定类型起名字。

4. 函数类型定义:语法形式有差异

虽然两者都能定义函数类型,但表达形式和适用场景有明显区别:

  • type 定义函数类型更简洁,和箭头函数写法高度一致:

    typescript 复制代码
    type FetchData = (url: string, params?: object) => Promise<any>;
  • interface 定义函数类型使用「调用签名」语法:

    typescript 复制代码
    interface FetchData {
      (url: string, params?: object): Promise<any>;
    }

interface 的调用签名有一个独特优势:适合定义带属性的函数对象(函数本身还有额外属性),在封装库、定义工具函数类型时非常常用:

typescript 复制代码
interface Counter {
  (): number;       // 调用签名:函数本身
  count: number;    // 函数的属性
  reset(): void;    // 函数的方法
}

5. 高级类型能力:type 独有的类型编程

TypeScript 的高级类型特性(映射类型、条件类型、infer 推断、模板字面量类型等),全部只能通过 type 来实现,interface 完全不支持。

我们日常使用的工具类型 PartialRequiredPick 等,本质上都是用 type 实现的:

typescript 复制代码
// 映射类型:只能用 type 实现
type MyPartial<T> = {
  [P in keyof T]?: T[P];
};

// 条件类型:只能用 type 实现
type IsString<T> = T extends string ? true : false;

如果你需要做类型体操、编写工具类型、处理复杂类型运算,那 type 是唯一选择。

6. 类实现的细节差异

在类 implements 的场景中,两者都可以被类实现,但有一个细节差异:

类可以 implements 一个 interface,也可以 implements 一个对象类型的 type。但如果 type 定义的是联合类型,类无法实现:

typescript 复制代码
type UserType = { id: number } | { name: string };
// ❌ 报错:类只能实现对象类型或对象交叉类型
class User implements UserType {}

interface 因为只能是对象类型,所以不存在这个问题,语义上也更符合 "类实现接口" 的面向对象概念。

三、实战选型:什么时候用哪个?

讲完所有区别,很多同学还是会纠结:写代码的时候到底该用哪个?

这里给你一套通用的选型原则,简单好记,也符合 TS 社区的主流实践:

表格

场景 推荐使用 核心原因
定义组件 Props、API 响应、公共对象契约 interface 可扩展、支持声明合并,语义清晰
基本类型别名、联合类型、元组 type interface 无法实现
映射类型、条件类型等工具类型 type 只有 type 支持类型运算
简单函数类型定义 type 写法更简洁直观
带属性的函数对象、混合类型 interface 调用签名语义更清晰
类实现接口、面向对象抽象 interface 符合面向对象设计语义
扩展第三方库、全局类型 interface 依赖声明合并特性

简单总结一句话:对象契约与可扩展场景用 interface,灵活组合与类型运算用 type

现在 TS 社区的主流趋势是:日常业务开发中 type 的使用频率越来越高,因为它更灵活、覆盖场景更广;而 interface 更多用于公共类型定义、库的类型声明等需要可扩展性的场景

相关推荐
Canace1 小时前
Fable 像素游戏复盘,Vibe Coding 的 10 条工程规则与赛车 Demo 实践
前端·人工智能·游戏开发
xx24061 小时前
智慧园区前端技能
前端
YHL1 小时前
⚛️ React `useState` 深入浅出
前端·react.js·前端框架
喝咖啡的女孩1 小时前
vibe coding一个云书房
前端
计算机魔术师1 小时前
为了考试作弊,AI 模型黑进了 Hugging Face——这已经不是科幻了
前端
天云数据1 小时前
从“LLM+工具”到Harness 工程:Lilian Weng新文的技术拆解,与一个生产级参考实现
java·前端·网络
三8441 小时前
WordPress SQL 注入漏洞分析:从 author__not_in 参数到 REST API 全链路
linux·前端·数据库
IT_陈寒1 小时前
Vite打包时踩了个坑,static资源去哪了?
前端·人工智能·后端
龙虾PRO1 小时前
2026 年 AI 智能体工具调用:ReAct 模式与函数调用怎么选才不踩坑
前端·人工智能·react.js