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
相关产品推荐
相关产品推荐

