前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库TypeScript unknown 和 any 区别
TyTypeScript类型系统基础

TypeScript 的 unknown 和 any 有什么区别,外部数据应该用哪个?

不知道输入是什么,可以如实保留未知;不必因此放弃后续使用位置的类型检查。

前端进阶之旅 · 一题精讲更新于 2026.09.06
TypeScript#类型系统基础#类型系统
先看核心答案读代码示例
理解线索

从未知输入到可用数据

  1. 接收输入承认边界外的数据可能具有任意形状
  2. 执行检查验证需要读取的字段及业务约束
  3. 暴露契约只把已经证明可用的数据交给后续逻辑

两者在编译后都不会生成保护代码,不能仅靠修改类型注解消除运行时错误。

核心回答

先记住这个答案

unknown 和 any 都可以接收许多不同类型的值,但使用规则差别很大。any 会让相关操作跳过大量静态检查,属性读取、调用和赋给具体类型都可能直接通过;unknown 要求先通过检查或其他证明缩小范围,才能执行依赖具体类型的操作。外部数据、未知异常和通用边界通常适合从 unknown 开始,再解析为可信结构。unknown 本身不验证数据,类型断言也不执行验证,真正的安全来自与目标契约匹配的运行时检查。

  • any 容易把未检查的信息传播到后续代码
  • unknown 保留使用前先证明类型的责任
  • 把数据标为 unknown 只是校验流程的起点

同样未知,使用时为何差别很大

函数接收 any 后调用 trim,即使输入是数字,编译器通常也不会阻止;错误会留到运行时。换成 unknown,调用位置必须先证明输入是字符串。这样未知信息被留在边界,而不会因为一次随意操作扩散成更多看似可信的值。

示例把检查和格式化放在同一小函数里,字符串可以继续使用方法,其他输入则走明确失败路径。预期错误注释演示未经检查的调用不能通过,实际业务不应保留那段错误操作,而应只暴露已检查的实现。

未知输入先检查再使用TypeScript
function unsafe(value: any) {
  return value.trim();
}
function rejected(value: unknown) {
  // @ts-expect-error unknown 尚未证明具有 trim
  return value.trim();
}
function readLabel(value: unknown): string {
  if (typeof value !== 'string') throw new TypeError('label must be a string');
  return value.trim();
}

unsafe 的类型检查不能保证 trim 存在,rejected 明确展示 unknown 阻止同一操作。readLabel 通过真实判断建立字符串证据,传入非字符串时会主动抛出可诊断错误。

外部 JSON 如何避免继续传播 any

某些解析接口返回 any。可以在接收位置把结果保留为 unknown,再交给解析函数,防止业务代码直接读取深层字段。解析函数需要验证当前功能实际依赖的结构、数组元素以及格式限制,不能只检查最外层是对象就宣布整个响应可信。

若服务端接口有生成类型,也仍要区分编译时契约与实际网络响应。部署不同步、缓存旧结构或错误响应都可能打破静态假设。可以根据边界可靠性选择校验范围,但应明确由哪一层承担验证责任,而不是让任意断言散落在组件中。

什么时候可能保留 any

迁移旧库或兼容极为动态的调用协议时,局部 any 有时是明确的工程选择。应尽量限制在适配器内部,通过小范围封装暴露稳定返回类型,并为关键行为提供运行验证。把整个项目统一改成 any 会失去编译器发现不匹配的价值。

双重断言经过 unknown 再转成目标类型,并没有补充任何证据,只是绕过部分可赋值性限制。如果确实需要断言,应能说明证据来自哪个受控约束;无法说明时,优先设计解析或守卫函数,而不是寻找让报错消失的写法。

回答前,多想一步

容易答错的地方

unknown 会自动检查网络响应
unknown 只限制静态使用方式,不会遍历字段或拒绝非法值;必须执行真实解析逻辑,之后才能把输入作为业务类型使用。
any 只影响当前这一行代码
从 any 读取或计算得到的值可能继续携带宽松类型,后续赋值也可能失去保护,因此应在边界尽早隔离并明确返回契约。
试着用自己的话回答

面试官还会怎么问?

unknown 能直接赋给 string 吗?

未经收窄通常不能,因为输入也可能是数字或对象;通过 typeof 等检查证明为字符串后,相应分支内才可以按字符串使用。

给 JSON.parse 加类型断言足够吗?

断言没有运行时验证效果。它只适合已有可靠外部保证的场景;面对不可信或可能变化的响应,应使用实际解析逻辑并处理失败。

捕获异常后为什么经常需要先判断类型?

JavaScript 可以抛出字符串、对象甚至空值,未知异常不保证具有 message 字段;应按 Error 实例或其他可识别结构分别处理。

从一道题,走向一组知识

把知识连起来

类型系统基础

TypeScript 如何把 unknown 安全收窄为业务对象,而不是直接断言?

进一步构造从 unknown 验证到业务对象的完整路径

类型收窄

TypeScript typeof 类型守卫能识别什么,为什么还要单独排除 null?

明确 typeof 能证明哪些类型以及对象分支的局限

参考资料

  • TypeScript:unknown Top Type
  • TypeScript:any

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同样未知,使用时为何差别很大
  3. 外部 JSON 如何避免继续传播 any
  4. 什么时候可能保留 any
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑