Skip to content

一、nullundefined 在 TS 中是什么?

TypeScript 里:

ts
null        // 一个值,表示“空”
undefined   // 一个值,表示“未定义”

它们 既是值,也是类型

ts
let a: null = null
let b: undefined = undefined

二、关键前提:strictNullChecks

现在99% 项目都开启了:

json
{
  "compilerOptions": {
    "strict": true
  }
}

等价于:

json
{
  "strictNullChecks": true
}

开 / 关的本质区别

❌ 未开启(老项目)

ts
let s: string

s = null        // ✅ 不报错
s = undefined   // ✅ 不报错

👉 极其危险,类型形同虚设

✅ 开启(现代 TS 项目,默认)

ts
let s: string

s = null        // ❌
s = undefined   // ❌

结论

nullundefined 不再是所有类型的子类型

三、正确使用 null / undefined 的方式

1️⃣ 显式声明可空

ts
let s: string | null
let t: string | undefined
let u: string | null | undefined
ts
s = null
t = undefined

👉 必须用联合类型

2️⃣ 对象属性中的可选 vs undefined

可选属性 ?

ts
interface User {
  name: string
  age?: number
}

等价于:

ts
age: number | undefined

但不等价于 null

ts
const u1: User = { name: 'Tom' }           // ✅
const u2: User = { name: 'Tom', age: 18 }  // ✅
const u3: User = { name: 'Tom', age: null } // ❌

👉 ? = 可能不存在,而不是 null

3️⃣ 函数参数中的 undefined

ts
function foo(x?: number) {}

等价于:

ts
function foo(x: number | undefined) {}
ts
foo()
foo(undefined)
foo(1)

四、null vs undefined 的实际使用约定(非常重要)

🔹 业界常见约定(强烈推荐)

场景用哪个原因
变量未初始化undefinedJS 原生语义
参数可选undefined? 语法
对象字段缺失undefinedJSON 习惯
主动“置空”null明确表达“空”
后端返回空值null数据库常见

示例

ts
let currentUser: User | null = null // 当前无用户

ts
let currentUser: User | undefined

语义更清晰

五、常见坑(前端必踩)

❌ 坑 1:直接访问可能为 null 的值

ts
function printLength(s: string | null) {
  console.log(s.length) // ❌
}

✅ 正确方式:缩小类型(类型守卫)

ts
function printLength(s: string | null) {
  if (s !== null) {
    console.log(s.length) // ✅
  }
}

或:

ts
if (s) { } // ⚠️ 会排除 '' 0 false

❌ 坑 2:DOM API

ts
const el = document.getElementById('app')
el.innerHTML = 'hi' // ❌

✅ 正确写法

ts
const el = document.getElementById('app')

if (el) {
  el.innerHTML = 'hi'
}

或断言(你非常确定存在):

ts
const el = document.getElementById('app')!

六、! 非空断言(慎用)

ts
el!.innerHTML = 'hi'

含义:

“我保证它不是 null / undefined”

⚠️ 运行时不会帮你检查

七、可选链 & 空值合并(TS + ES2020 神器)

1️⃣ 可选链 ?.

ts
user?.profile?.name

2️⃣ 空值合并 ??

ts
const name = user.name ?? '匿名'

对比:

ts
||   // 会把 '' 0 false 当成假
??   // 只关心 null / undefined

八、总结一句话(记住就行)

TS 不允许你“假装不存在 null / undefined”

你必须:

  • 用联合类型声明
  • 用判断缩小
  • ?. / ??
  • 谨慎用 !