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()); // 无类型错误
修复说明
- 统一泛型捕获空值类型:用泛型
N约束为null | undefined,替代原有的两个重载,让TypeScript能准确推断输入数组的空值类型,并在返回值中保持一致,解决了原代码返回类型不匹配的问题(错误2)。 - 精确约束函数参数类型:实现函数添加了泛型约束,确保
this的类型与返回值类型对应,同时通过运行时判断排除空值后,用value as T做安全断言,让TypeScript确认传给op的参数一定是非空的T类型,解决了v可能为null的错误提示(错误1)。 - 避免
any类型滥用:移除原实现中的any,改用明确的泛型类型,保证类型安全。
内容的提问来源于stack exchange,提问作者Alex Craft
相关产品推荐
相关产品推荐

