You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中如何区分null与undefined?及mapIfPresent类型定义修正

TypeScript中null与undefined的区分
  • 语义层面
    • undefined代表值未被初始化:比如声明变量未赋值、函数无返回值、访问对象不存在的属性时都会返回它。
    • null代表值被主动设为空:通常用于明确表示某个操作没有结果,比如数据库查询无匹配项时返回null。
  • 类型系统层面
    • 开启strictNullChecks严格模式后,null和undefined是独立的类型,不能互相赋值;关闭该模式时,两者会被视为可兼容的“空值”。
    • 可通过联合类型(如number | null、string | undefined)将空值类型与其他类型组合。
  • 运行时行为
    • 松散相等==下,null == undefined返回true;严格相等===下,两者不相等。
    • 可选链?.、空值合并??会同时处理null和undefined。
修复mapIfPresent方法的类型定义

原代码的两个重载无法精准区分null和undefined的场景,导致类型推断错误。以下是正确的实现方案:

完整修复代码

export {}

declare global {
  interface Array<T> {
    mapIfPresent<R, N extends null | undefined>(
      this: (T | N)[],
      op: (v: T, i: number) => R
    ): (R | N)[]
  }
}

Array.prototype.mapIfPresent = function<T, R, N extends null | undefined>(
  this: (T | N)[],
  op: (v: T, i: number) => R
): (R | N)[] {
  const result: (R | N)[] = new Array(this.length);
  for (let i = 0; i < this.length; i++) {
    const value = this[i];
    result[i] = value === null || value === undefined ? value : op(value as T, i);
  }
  return result;
}

// 测试用例
const list: (number | null)[] = [1, null];
const result: (number | null)[] = list.mapIfPresent(v => v + 1); // 无类型错误

const undefList: (string | undefined)[] = ["hello", undefined];
const undefResult: (string | undefined)[] = undefList.mapIfPresent(v => v.toUpperCase()); // 无类型错误

修复说明

  1. 统一泛型捕获空值类型:用泛型N约束为null | undefined,替代原有的两个重载,让TypeScript能准确推断输入数组的空值类型,并在返回值中保持一致,解决了原代码返回类型不匹配的问题(错误2)。
  2. 精确约束函数参数类型:实现函数添加了泛型约束,确保this的类型与返回值类型对应,同时通过运行时判断排除空值后,用value as T做安全断言,让TypeScript确认传给op的参数一定是非空的T类型,解决了v可能为null的错误提示(错误1)。
  3. 避免any类型滥用:移除原实现中的any,改用明确的泛型类型,保证类型安全。

内容的提问来源于stack exchange,提问作者Alex Craft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:52:27