面试题:TypeScript 异步状态建模与穷尽检查
本题考察你能否用 TypeScript 准确表达业务状态,并利用类型系统减少运行时错误。

文章目录 3
题目
下面的异步请求状态存在什么问题?
interface User {
id: number;
name: string;
}
interface UserState {
loading: boolean;
data?: User;
error?: string;
}请重新设计 UserState,满足以下要求:
支持
idle、loading、success、error四种状态。success状态一定有data。error状态一定有错误信息。实现
renderUser(state),并让 TypeScript 在遗漏状态分支时能够报错。
题解
原设计的问题是:loading、data、error 相互独立,能够表示业务上不合理的状态,例如请求成功却没有 data。
可以使用可辨识联合类型:
interface User {
id: number;
name: string;
}
type UserState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User }
| { status: 'error'; error: string };实现渲染和穷尽检查:
function renderUser(state: UserState): string {
switch (state.status) {
case 'idle':
return '尚未加载';
case 'loading':
return '加载中';
case 'success':
return `用户:${state.data.name}`;
case 'error':
return `加载失败:${state.error}`;
default: {
const exhaustiveCheck: never = state;
return exhaustiveCheck;
}
}
}核心原理:
status是判别字段,TypeScript 会根据它自动收窄类型。success状态一定存在data。error状态一定存在error。新增状态但忘记处理时,
never穷尽检查会产生编译错误。
面试时的推荐表达
可以这样回答:
原来的
loading、data和error是相互独立的字段,可以组成很多业务上不合法的状态。单独增加status也不够,因为success仍然不能保证存在data。我会使用以status为判别字段的联合类型,让每种状态携带自己的数据。处理状态时,TypeScript 可以根据status自动收窄类型;再通过never进行穷尽检查,使新增状态但遗漏处理逻辑时能够在编译阶段报错。如果多个接口具有相同状态结构,还可以抽成AsyncState<T, E>泛型。
相关文章
- 面试题-基础
Vue 3 响应式解构:为什么替换 user 后出现“李四 / 王五”
通过一道 Vue 3 代码题,区分 reactive 对象解构、嵌套属性修改与对象替换的行为,并用 toRef 保持源属性关联。文章保留首次作答及追问补答,说明从误判到纠正的过程。
- 面试题-基础
Vue 3 编辑弹窗:草稿状态、取消重开与父子数据契约
以一个始终挂载的姓名编辑弹窗为场景,给出覆盖数据归属、保存取消、重开初始化和外部更新冲突的完整 Vue 3 解法。结合首次回答与递进补答,说明本地草稿、脏标记和版本校验各自解决的问题。
- 面试题-基础
JavaScript 浅拷贝、深拷贝与 structuredClone:前端状态更新的正确方式
通过一道对象复制代码题,梳理 JavaScript 浅拷贝、JSON 深拷贝、structuredClone 和 transferable object 的边界,并解释 React 结构共享与 Vue 3 响应式更新的差异。
评论
0 条评论会在审核后展示,邮箱不会公开。