TypeScript 可选属性与空值处理完全指南
? 可选属性、strictNullChecks、undefined vs null 的语义差异与空值安全工具函数——把"undefined 不是函数"类错误消灭在编译期。
可选属性 name?: string 等价于 name: string | undefined——访问前必须处理不存在的情况(可选链 ?.、空值合并 ??)。开启 strictNullChecks 后,"可能是 undefined"成为编译期必须回答的问题。
缺失值的问题
JS 的头号运行时错误:"Cannot read properties of undefined"。TS 的答案:让缺失在类型中显式可见。
可选属性与严格空检查
interface User {
name: string;
bio?: string; // 可能不存在
}
function getBio(user: User): string {
return user.bio ?? '暂无简介'; // ?? 空值合并:undefined/null 时给默认
}
strictNullChecks 开启后:user.bio.toUpperCase() 直接编译报错——必须处理空值分支。
undefined vs null vs 可选
- undefined:"没赋值"(可选属性缺失、参数未传);
- null:"明确的空"(API 返回的空值、数据库 NULL);
- 可选 ?:属性可以不存在。
实践惯例:API 层尊重对方的选择(null 或缺失),应用内部统一 undefined(可选属性),?? 对两者一视同仁。
空值安全工具
// 可选链:深层访问不炸
const city = user?.address?.city;
// 空值合并:??(只在 null/undefined 时生效,0/'' 不被误伤)
const count = data.count ?? 0;
// 空值守卫函数
function requireNonNull<T>(value: T | null | undefined, name: string): T {
if (value == null) throw new Error(`${name} 不应为空`);
return value;
}
?? 与 || 的区别:|| 把 0、''、false 也当空——数字与字符串场景用 ??。
常见问题(FAQ)
Q:老项目怎么开 strictNullChecks?
渐进:先开 strict 其他子项,strictNullChecks 单独攻坚(报错量大);或按目录逐步覆盖(tsconfig 的 references/多配置)。
Q:可选属性和 | undefined 有区别吗?
exactOptionalPropertyTypes 开启后有:? 允许"不存在",| undefined 要求"必须存在但可以 undefined"。默认配置下语义相同。
Q:断言非空(!)何时合理?
你确定逻辑上必有值(刚 push 完就 pop)时可用;频繁出现 ! 是设计问题的信号——应该用收窄或守卫。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。