跳到主要内容前端高频面试题:TypeScript 核心概念与实战解析 | 极客日志TypeScript大前端
前端高频面试题:TypeScript 核心概念与实战解析
TypeScript 作为 JavaScript 的超集,通过静态类型系统提升代码可维护性。内容涵盖基础类型、接口与泛型、类型守卫等核心概念,结合 Vue 集成与常见错误处理,提供从入门到进阶的实战指南。重点解析了类型断言、联合类型、条件类型及严格模式配置,帮助开发者规避常见陷阱,构建健壮的 TS 应用。
晚风叙旧30 浏览 TypeScript 核心概念与实战解析
TypeScript 作为 JavaScript 的超集,通过引入静态类型系统显著提升了代码的可维护性与健壮性。以下整理了面试中高频出现的 TypeScript 知识点,涵盖基础类型、高级特性及工程化实践。
1. TypeScript 是什么?与 JavaScript 的核心区别
TypeScript (TS) 是 JavaScript 的超集,在保留 JS 语法的基础上增加了静态类型系统。最终编译为纯 JS 运行,兼容所有 JS 环境。其核心价值在于提升代码可维护性并减少运行时错误。
与 JavaScript 的关键差异:
- 类型系统:TS 拥有静态类型(编译阶段检查),JS 则是动态类型(运行时确定)。
- 编译阶段:TS 需通过编译器(如
tsc)编译校验后才能运行;JS 可直接执行。
- 特性补充:TS 新增接口、泛型、枚举等原生类型特性;JS 无此能力。
- 开发体验:TS 支持 IDE 智能提示与自动补全,能提前预警类型错误。
2. 基本数据类型
TS 支持原始类型与特殊类型,实习中需重点关注显式标注与特殊类型的用途。
- 原始类型:
string:字符串,如 let name: string = "张三"。
number:数字(含整数、浮点数)。
boolean:布尔值(true/false)。
null / undefined:空值与未定义,开启 strictNullChecks 后需单独识别。
symbol:唯一标识(ES6 特性)。
bigint:大整数类型。
- 特殊类型:
any:任意类型,关闭类型检查,不推荐滥用。
unknown:未知类型,比 any 安全,使用前需断言。
void:无返回值类型,常用于函数。
never:永不存在的类型,如抛出错误的函数或无限循环。
3. 接口(Interface)与类型别名(Type Alias)的区别
两者均可定义对象/函数类型,但适用场景不同。
- 相同点:均支持泛型,均可定义对象结构。
- 核心区别:
- 扩展方式:Interface 使用
extends;Type Alias 使用交叉类型 &。
- 声明合并:Interface 支持同名合并;Type Alias 不支持,同名会报错。
- 适用范围:Interface 仅用于对象/函数;Type Alias 可定义基础类型、联合类型等。
- 使用建议:优先用 Interface 定义组件 Props 或 API 数据结构(便于扩展);优先用 Type Alias 处理联合类型或复杂复用。
4. 泛型(Generic)的作用与实例
泛型允许在定义时不指定具体类型,使用时动态传入,类似函数的参数传递。
- 为什么需要:避免使用 导致类型丢失,实现一套逻辑支持多种类型。
any
实例:通用数组工具函数。function getFirstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const strArr: string[] = ["a", "b"];
const firstStr = getFirstElement(strArr);
5. 类型断言(Type Assertion)
当 TS 无法自动推断类型时,开发者手动指定实际类型。仅在编译阶段生效。
- 两种常用方式:
- 尖括号语法:
<Type>value。不支持 JSX 场景。
- as 语法:
value as Type。推荐,支持所有场景。
- 注意事项:不能断言完全无关的类型;避免滥用,优先依赖自动推断。
6. any、unknown、never、void 对比
| 类型 | 含义 | 关键特性 | 场景 |
|---|
any | 任意类型 | 关闭检查,可调用任意方法 | 临时兼容旧代码 |
unknown | 未知类型 | 安全的 any,需断言后使用 | 接收外部数据 |
void | 无返回值 | 仅函数可用 | 日志类函数 |
never | 永不存在 | 不能赋值给任何类型 | 抛出错误或死循环 |
7. 可选属性与只读属性
- 可选属性:属性名后加
?,表示可省略。访问时需判断是否存在。
- 只读属性:属性名前加
readonly,初始化后不可修改(浅只读)。
interface User {
readonly id: string;
name: string;
age?: number;
}
8. 联合类型与交叉类型
- 联合类型 (
|):变量可以是多个类型中的任意一个。常用于处理多类型参数。
- 交叉类型 (
&):合并多个类型的属性。常用于合并用户信息与权限信息。
type ID = string | number;
type Admin = User & Permission;
9. 类型守卫(Type Guard)
在运行时检查变量类型,缩小范围以便 TS 推断具体类型。
- 常用方式:
typeof:判断基础类型。
instanceof:判断引用类型。
in:判断对象是否包含某属性。
- 自定义守卫:返回
param is Type 的函数。
10. TypeScript 集成到 Vue 项目
以 Vue3 + Vite 为例,推荐使用 <script setup lang="ts">。
- 配置要点:
tsconfig.json:开启 strict: true,配置 lib 和 types。
vite.config.ts:使用 TS 编写配置。
- 组件示例:
<script setup lang="ts">
import { ref } from 'vue';
const props = defineProps<{ username: string; age?: number }>();
const count = ref(0);
</script>
11. 枚举(Enum)
- 数字枚举:默认从 0 开始递增,支持反向映射。
- 字符串枚举:语义更清晰,无反向映射冗余。建议优先使用。
12. 声明文件(.d.ts)
描述 JS 模块类型的文件,解决 TS 无法识别 JS 库的问题。
- 场景:引入无类型声明的第三方库,或自定义 JS 工具函数。
- 写法:
declare module "xxx" { ... }。
13. 异步函数类型处理
异步函数返回值为 Promise<T>,T 为成功后的数据类型。
interface User { id: string; name: string; }
async function fetchUsers(): Promise<User[]> {
const res = await fetch('/api/users');
return res.json();
}
14. 索引签名(Index Signature)
interface ScoreMap {
[key: string]: number;
}
15. 类的继承与多态
- 继承:子类使用
extends,构造函数需调用 super()。
- 多态:子类重写父类方法,同一方法在不同子类有不同行为。
16. readonly 与 const 的区别
- 作用对象:
readonly 用于类/接口属性;const 用于变量。
- 限制:
readonly 限制属性重新赋值;const 限制变量引用不可变(对象内部仍可改)。
17. 条件类型(Conditional Types)
type ElementOf<T> = T extends Array<infer U> ? U : T;
18. 函数类型定义
覆盖函数声明、表达式、可选参数、默认参数及剩余参数。
function greet(name: string, age?: number): string { ... }
const add: (a: number, b: number) => number = (a, b) => a + b;
19. 模块系统与 JS 的区别
- 类型导出:TS 支持
export type/import type,明确区分类型与值。
- 路径解析:支持
baseUrl 和 paths 配置简化导入。
- 类型检查:导入时即检查类型存在性。
20. 常见错误处理:属性不存在
遇到 'X' 上不存在属性 'Y' 错误,通常原因及解法:
- 类型定义不全:补充接口属性。
- 推断错误:使用类型断言或显式标注。
- 联合类型未缩小:使用类型守卫。
21. 映射类型(Mapped Types)
批量创建新类型,常用内置类型包括 Partial, Required, Readonly, Pick, Omit。
type PartialUser = Partial<User>;
type UserName = Pick<User, 'name'>;
22. DOM 元素类型处理
TS 提供专属类型(如 HTMLInputElement),需断言才能调用专属属性。
const input = document.getElementById('username') as HTMLInputElement;
input.value = 'test';
23. 严格模式(strict: true)
开启后启用一系列严格规则,如 noImplicitAny, strictNullChecks 等,强制严谨编码。
24. 泛型约束(Generic Constraints)
function getLength<T extends { length: number }>(value: T): number {
return value.length;
}
25. 实习常见问题与解决
- API 类型不匹配:检查字段是否为可选(如
age?: number),并在渲染前做空值判断。
- 第三方库无类型:优先安装
@types 包,若无则手动编写 .d.ts 声明文件。
26. 类型推断(Type Inference)
let username = "张三";
const user = { name: "张三", age: 22 };
27. 函数重载
function formatDate(date: Date): string;
function formatDate(date: Date, format: string): string;
function formatDate(date: Date, format?: string): string { ... }
28. 命名空间(Namespace)与模块
- Namespace:单文件内组织代码,易污染全局,现代项目较少用。
- Module:独立文件,支持
import/export,是现代标准。
29. 抽象类(Abstract Class)
不能实例化的基类,用于定义子类公共接口。抽象方法必须在子类中实现。
30. 循环依赖处理
- 提取公共类型:将共享类型移至独立模块。
- 延迟导入:使用动态
import() 避免初始化冲突。
31. 字面量类型(Literal Types)
表示具体值的类型,比普通类型更精确,常用于限制取值范围。
type ButtonType = "primary" | "secondary";
32. infer 关键字
在条件类型中推断类型变量,常用于提取泛型中的部分信息(如返回值、数组元素)。
33. 全局变量类型定义
通过扩展 Window 接口或在 .d.ts 文件中声明,告知 TS 全局变量的类型。
declare global {
interface Window {
appConfig?: { apiUrl: string };
}
}
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online