关键在于不假设、不信任、不跳过检查:所有外部数据必须显式验证和类型收窄后才进入业务逻辑,优先用typeof、array.isarray()、??、?.、unknown等机制做空值防护、结构校验与类型安全收窄。

安全处理未知数据类型的输入,关键在于不假设、不信任、不跳过检查——所有外部来源的数据(用户输入、API 响应、URL 参数、localStorage 读取等)都必须经过显式验证和类型收窄,才能进入业务逻辑。
先做基础类型判断和空值防护
任何输入进来第一件事不是用,而是“看它到底是什么”:
- 用 typeof 区分原始类型(
"string"、"number"、"boolean"、"undefined"、"object"、"function"、"symbol"、"bigint"),注意null的typeof是"object",需单独用value === null判断 - 用 Array.isArray() 替代
typeof arr === "object"判断数组 - 对可能为
null或undefined的值,优先用 ??(空值合并)获取默认值,而非||(会误判0、""、false) - 字符串务必 .trim() 后再判断是否为空,避免空格干扰
结构化数据要逐层校验字段存在性
对象或嵌套数据不能直接解构或访问 obj.user.name,必须确认路径完整:
- 用 in 操作符 或 hasOwnProperty() 确认关键属性是否存在,例如
"name" in user - 深层访问推荐用 可选链(?.),如
user?.profile?.avatar,避免报错 - 解构时设置默认值,如
{ id = 0, name = "未知" } = data || {},防止data为null或undefined - 对 API 返回的 JSON,先用 safeParseJSON 封装(含
trim()、JSON.parsetry-catch、类型二次校验),再做字段检查
数值与字符串要做格式清理和范围约束
用户输入的“数字”往往是字符串,且可能含非法字符或越界值:
- 用 Number(input) 转换后,立刻用 isNaN() 判断是否有效,不要依赖
parseInt的宽松解析 - 整数用
Math.trunc(Number(str))或~~Number(str)更安全;小数用parseFloat(str)并配合正则/^-?\d+(\.\d+)?$/预检 - 字符串输入需结合正则白名单过滤,如邮箱用
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,禁止盲目replace(/<script>/gi, "")</script>这类黑名单式清洗 - 有明确业务边界的(如年龄 0–120、金额 ≥ 0),转换后必须加范围校验
用 unknown 替代 any 实现类型安全收窄
在 TypeScript 中,接收任意输入时声明为 unknown 而非 any,能强制你在使用前完成类型检查:
-
let input: unknown;→ 不能直接调用方法、访问属性、参与运算 - 必须通过
typeof、Array.isArray()、自定义类型守卫(如isUser(obj))或instanceof收窄后,才能安全使用 - 例如:
if (typeof input === "string") { input.trim(); }—— 编译器此时才允许.trim() - 这比运行时崩溃更早暴露问题,是静态层面的防御加固
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











