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

TypeScript如何优雅校验对象属性并在值为null时抛出异常?

优雅处理TypeScript对象null属性校验与类型转换方案

先优化重复类型定义

首先用TypeScript泛型工具类型自动生成MyType的非null版本,避免手动复制属性的冗余操作:

type MyType = {
  key1?: string | null
  key2?: string | null
  key3?: string | null
  // 更多属性...
};

// 通用工具类型:移除对象所有属性的null类型
type NotNull<T> = {
  [K in keyof T]: Exclude<T[K], null>
};

// 自动生成非null版本的类型,无需手动维护
type MyTypeNotNull = NotNull<MyType>;

function logMyType(type: MyTypeNotNull) {
  console.log(type);
}

方案一:用断言函数实现校验+类型断言

写一个通用的断言函数,遍历对象所有属性检查是否存在null,同时通过asserts语法告诉TypeScript:执行完这个函数后,对象的类型已经是NotNull<T>。

// 通用断言函数:检查对象是否含null属性,是则抛出异常
function assertNoNullProperties<T>(obj: T): asserts obj is NotNull<T> {
  for (const key in obj) {
    // 只检查自身可枚举属性,避免遍历原型链
    if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] === null) {
      throw new Error(`属性 ${key} 不能为null`);
    }
  }
}

const myType: MyType = {
  key1: 'myKey1',
  // key2 省略
  key3: null,
  // 更多属性...
};

const run = (value: MyType) => {
  // 执行断言,存在null则抛出异常
  assertNoNullProperties(value);
  // 此时TypeScript会自动识别value为MyTypeNotNull类型
  logMyType(value);
};

run(myType); // 执行时会抛出错误:属性 key3 不能为null

方案二:用类型守卫函数实现校验

如果更倾向于用条件判断而非断言语法,可以写一个类型守卫函数,返回布尔值的同时缩小对象类型:

// 通用类型守卫:检查对象是否不含null属性
function hasNoNullProperties<T>(obj: T): obj is NotNull<T> {
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] === null) {
      return false;
    }
  }
  return true;
}

const run = (value: MyType) => {
  if (!hasNoNullProperties(value)) {
    throw new Error("对象包含null属性");
  }
  // 条件分支内TypeScript会识别value为MyTypeNotNull类型
  logMyType(value);
};

方案优势

  • 代码复用:断言/守卫函数是通用的,可直接用于其他类似结构的对象类型
  • 维护成本低:新增MyType属性时,无需修改校验逻辑和MyTypeNotNull类型,自动同步
  • 避免冗余:代替大量重复的if (xxx === null)判断,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 07:33:20