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

TypeScript:实现校验对象值非空的断言类型守卫

如何为断言类型守卫函数assertNonEmpty定义断言类型?

我已经实现了一个判断变量是否为空(包含null、undefined、''、[]、{}、0)的方法isNullOrUndefinedOrEmpty,代码运行正常。现在需要编写断言类型守卫函数assertNonEmpty,当传入的对象参数中存在空值时抛出错误,请问该如何定义该函数的断言类型?

已有代码

declare const emptyObjectSymbol: unique symbol;
type EmptyObject = { [emptyObjectSymbol]?: never };

/**
 * Return true if "value" is: null, undefined, '', [ ], { }, 0
 *
 * **Example**
 * 
 * ```js
 * const result = isNullOrUndefinedOrEmpty(""); // return true
 * const result = isNullOrUndefinedOrEmpty(null); // return true
 * const result = isNullOrUndefinedOrEmpty(undefined); // return true
 * 
 * const result = isNullOrUndefinedOrEmpty(new Date()); // return false
 * const result = isNullOrUndefinedOrEmpty("Hello World"); // return false
 * ```
 */
export const isNullOrUndefinedOrEmpty = (value: any): value is null | undefined | '' | [] | EmptyObject | 0 => {
  if (value === null || value === undefined || value === '' || value === 0) {
    return true;
  }
  if (typeof value === 'number' && isNaN(value)) {
    return true;
  }
  if (typeof value === 'object') {
    if (Array.isArray(value)) {
      return value.length <= 0;
    } else {
      return Object.keys(value).length === 0 && value.constructor === Object;
    }
  }
  return false;
};

解决方案

要实现assertNonEmpty的断言类型,我们需要先定义辅助类型描述"非空"属性,再通过映射类型确保对象所有属性满足非空要求:

1. 定义辅助类型

先定义NonEmpty类型排除isNullOrUndefinedOrEmpty识别的所有空值类型,再通过映射类型生成全属性非空的对象类型:

// 排除所有被isNullOrUndefinedOrEmpty判定为空的类型
type NonEmpty<T> = T extends null | undefined | '' | [] | EmptyObject | 0 ? never : T;

// 映射类型:将对象的每个属性转换为非空类型
type NonEmptyObject<T> = {
  [K in keyof T]: NonEmpty<T[K]>;
};

2. 完善assertNonEmpty函数

断言类型需要同时保证参数本身不为null/undefined,且所有属性均为非空类型,最终实现如下:

type NonEmpty<T> = T extends null | undefined | '' | [] | EmptyObject | 0 ? never : T;
type NonEmptyObject<T> = {
  [K in keyof T]: NonEmpty<T[K]>;
};

function assertNonEmpty<T>(params: T): asserts params is NonEmptyObject<T> & NonNullable<T> {
  if (params === null || params === undefined) {
    throw new Error(`Invalid params`);
  }
  for (const key in params) {
    const value = params[key];
    if (isNullOrUndefinedOrEmpty(value)) throw new Error(`Empty ${key}`);
  }
}

效果验证

使用该函数后,TypeScript会自动推导参数为全属性非空的对象类型,无需额外空值检查:

interface User {
  name: string | null;
  age: number | 0;
  tags: string[] | [];
}

const user: User = { name: "Alice", age: 25, tags: ["frontend"] };

assertNonEmpty(user);
// 此时user类型被推断为:{ name: string; age: number; tags: string[]; }
user.name.toUpperCase(); // 无类型报错,TypeScript已确认属性非空

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:32:02