TypeScript是否存在属性守卫?如何实现length属性校验逻辑
TypeScript 属性守卫实现方案
1. 定义RequireLength类型
先定义你需要的RequireLength类型,用来强制约束对象必须包含length属性:
type RequireLength = { length: number; };
这个类型逻辑很直接,只要是带有number类型length属性的对象,都能满足它的约束。
2. 实现hasLength类型谓词函数
接下来编写检测对象是否拥有length属性的类型守卫函数。这里推荐用unknown作为参数类型(比any更安全,避免隐式类型放宽),泛型不是必须的,但如果想保留原对象的其他属性类型,泛型会更实用:
基础版(无泛型)
function hasLength(arg: unknown): arg is RequireLength { // 先判断arg是有效对象,再验证length属性的存在与类型 return typeof arg === 'object' && arg !== null && 'length' in arg && typeof (arg as RequireLength).length === 'number'; }
进阶版(带泛型,保留原类型)
如果希望类型守卫后不丢失原对象的其他属性类型,可以用泛型结合交叉类型:
function hasLength<T>(arg: T): arg is T & RequireLength { return typeof arg === 'object' && arg !== null && 'length' in arg && typeof (arg as T & RequireLength).length === 'number'; }
这种写法下,当你传入一个既有length又有其他属性的对象时,守卫后TypeScript能识别出原对象的所有属性,而不只是length。
3. 实现LenGtZero函数
最后写判断length大于0的函数,既可以直接接受RequireLength类型参数,也可以结合上面的类型守卫做前置检查:
// 直接约束参数类型 function LenGtZero(obj: RequireLength): boolean { return obj.length > 0; } // 结合类型守卫,兼容unknown参数并自动缩小类型 function LenGtZero(arg: unknown): boolean { if (hasLength(arg)) { // 此处arg已被TypeScript推断为RequireLength类型 return arg.length > 0; } return false; }
关键细节说明
- 为什么用
unknown:它是TypeScript中最安全的顶层类型,必须经过明确的类型检查才能进行操作,避免了any带来的类型不安全问题。 - 泛型是否必要:基础场景下不需要,但如果要保留原对象的完整类型信息,泛型+交叉类型是最优解。
- 不需要
keyof:我们是直接检测特定属性length的存在,keyof多用于遍历类型的键集合,这里用不到。
内容的提问来源于stack exchange,提问作者dev-travel
相关产品推荐
相关产品推荐

