TypeScript 前端高频面试题精选与实战解析
TypeScript(TS)如今已是现代前端开发的标配,尤其在 React、Vue、Angular 等主流框架中,几乎是大厂面试的必考点。当前的面试趋势更看重类型安全、高级类型工具的实际应用以及 tsconfig 的配置细节。下面我整理了 20+ 道高频题,涵盖基础、进阶到高级类型体操,并附带代码示例和思路解析。
基础篇:核心概念与价值
1. TypeScript 是什么?和 JavaScript 有啥区别?
简单来说,TS 是 JS 的超集(superset),由微软开发,最终编译成纯 JS 运行。两者的核心差异在于:
- 类型检查时机:TS 在编译时进行静态类型检查,能提前捕获错误;JS 则是动态类型,错误往往在运行时才暴露。
- 特性支持:TS 原生支持接口、泛型、枚举、装饰器等面向对象特性。
- 构建流程:TS 需要编译器(tsc)处理,JS 则可直接执行。
- 维护成本:TS 虽然增加了学习曲线,但显著提升了大型项目的可维护性和 IDE 的智能提示能力。
2. 为什么大厂项目都强制用 TypeScript?
这不仅仅是跟风,而是有实实在在的好处:
- 类型安全:拼写错误或类型不匹配能在编译阶段被发现,大幅减少线上 Bug。
- 重构友好:IDE 的重命名、跳转定义、自动补全功能在 TS 下非常可靠。
- 团队协作:类型定义本身就是一种文档,明确了模块间的接口契约。
- 生态成熟:React/Vue/Angular 官方均强烈推荐 TS。
- 规模效应:当代码量达到一定规模,纯 JS 容易失控,TS 能有效约束边界。
3. 基本类型有哪些?
包括原始类型(boolean, number, string, null, undefined, symbol, bigint, void)、对象类型(object, array, tuple, enum)以及特殊类型(any, unknown, never)。
4. any、unknown、never 到底怎么选?
| 类型 | 描述 | 使用场景 | 安全性 |
|---|---|---|---|
| any | 任意类型,关闭检查 | 迁移旧项目或临时绕过 | 低(慎用) |
| unknown | 未知类型,需先收窄 | API 返回不确定类型 | 高(推荐) |
| never | 永不存在的值 | 抛出异常的函数或底部类型 | - |
看个实际例子,unknown 比 any 更安全:
let val: unknown = 'hello';
if (typeof val === 'string') {
// 类型收窄后,这里可以安全调用 string 方法
console.log(val.toUpperCase());
}
中级篇:编码实战与类型推导
这一部分主要考察对联合、交叉、泛型及类型守卫的理解。
1. 类型收窄(Type Narrowing)有哪些方式?
除了常见的 typeof、instanceof、in 操作符,还可以利用字面量守卫或自定义 is 关键字。比如处理参数类型不一致时:
function padLeft(value: string, padding: string | number) {
if (typeof padding === 'number') {
// 这里 padding 被收窄为 number
return Array(padding + 1).join(' ') + value;
}
return padding + value;
}
2. 联合类型(|)和交叉类型(&)的区别?
- 联合类型:值可以是其中一种,如
string | number。 - 交叉类型:值必须同时满足所有条件,常用于对象合并。
type A = { a: string };
type B = { b: number };
type C = A & B; // { a: string; b: number }
3. 泛型(Generics)的应用场景?
泛型让组件具备复用性,支持类型参数化。常见于数组工具、Promise、React 组件 Props 等。
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>('hello'); // T 推断为 string
4. interface 和 type 该怎么选?
这是一个经典问题。简单总结:
- interface:适合定义对象结构,支持声明合并(同名接口自动扩展),便于扩展。
- type:适合定义联合类型、元组、映射类型或原始类型别名。
推荐策略:对象/接口优先用 interface,复杂类型组合用 type。
interface User {
name: string;
}
// 同名接口会自动合并
interface User {
age?: number;
}
type ID = string | number;
高级篇:类型体操与配置优化
大厂深挖环节,通常涉及内置工具类型和高级语法。
1. tsconfig.json 关键配置
target:编译目标(如 es2020)。module:模块系统(esnext/commonjs)。strict:强烈建议开启,包含所有严格检查。noImplicitAny:隐式 any 报错。strictNullChecks:严格检查 null/undefined。esModuleInterop:优化 CommonJS 模块导入。skipLibCheck:跳过库文件类型检查,提升编译速度。
2. 映射类型(Mapped Types)
通过 [K in keyof T] 遍历键来创建新类型,这是实现工具类型的基础。
type Optional<T> = {
[K in keyof T]?: T[K];
}; // 等价于 Partial<T>
3. 条件类型(Conditional Types)
类似三元运算符的类型版本:T extends U ? X : Y。
type IsString<T> = T extends string ? 'yes' : 'no';
type Test1 = IsString<'hello'>; // 'yes'
4. 常用工具类型
Partial<T>:所有属性可选。Required<T>:所有属性必选。Readonly<T>:所有属性只读。Pick<T, K>/Omit<T, K>:挑选或排除属性。Record<K, T>:键为 K,值为 T 的对象。Exclude<T, U>/Extract<T, U>:从联合类型中排除或提取。
示例:
type User = { name: string; age: number };
type PartialUser = Partial<User>; // { name?: string; age?: number }
实战应用:框架集成
1. React/Vue 中的 TS 实践
- React:使用
.tsx后缀,Props 定义推荐使用interface或type,配合useState时注意泛型推断。 - Vue 3:在
<script setup lang="ts">中使用defineProps()定义类型,体验更佳。
2. 第三方库没有类型定义怎么办?
首选方案是安装 @types/库名(DefinitelyTyped)。如果实在没有,可以使用 declare module '库名' 声明,或者极端情况下用 any 断言,但这会牺牲类型安全,需谨慎。
面试建议
- 准备项目:最好有一个 TS + React/Vue 的个人项目,面试时能具体说明类型如何提升了代码质量。
- 多练类型体操:LeetCode TS 版或 GitHub 上的 Type Challenges 是很好的练习材料。
- 关注新特性:留意 TS 5.x 的新特性,如 const type parameters 等。
这些题目覆盖了大部分大厂考察点,背熟概念的同时更要理解背后的原理,这样在面试中才能灵活应对。

