TypeScript如何编写通用类型守卫判断数组为泛型T的数组类型
实现通用数组类型守卫方案
TypeScript 泛型属于编译期语法,运行时会完全擦除类型信息,因此你无法直接只通过传入泛型参数T完成运行时校验,必须额外传入对应类型的单元素校验规则。
通用实现代码
/** * 通用数组类型守卫 * @param arr 待校验的目标值 * @param isItem 单个元素的类型校验函数 * @returns 校验通过返回true,且TS会自动将输入收窄为T[]类型 */ const isArrayOf = <T>(arr: unknown, isItem: (item: unknown) => item is T): arr is T[] => { // 先判断目标是不是数组 if (!Array.isArray(arr)) return false // 遍历校验所有元素都符合T的规则 return arr.every(isItem) }
结合你的场景的使用示例
// 业务类型定义 interface NewType { foo: string bar: number } // 先编写单个NewType元素的校验函数 const isNewType = (item: unknown): item is NewType => { return ( typeof item === 'object' && item !== null && 'foo' in item && typeof (item as NewType).foo === 'string' && 'bar' in item && typeof (item as NewType).bar === 'number' ) } // 测试用例 const arr: any[] = [ { foo: "bleh1", bar: 1 }, { foo: "bleh2", bar: 2 }, ] // 使用类型守卫 if (isArrayOf(arr, isNewType)) { // 这里arr会被自动收窄为NewType[]类型,可安全访问成员属性无TS报错 console.log(arr[0].foo) }
补充说明
- 如果需要校验嵌套对象、联合类型等复杂结构,只需要修改对应的单元素校验函数即可,不需要调整
isArrayOf的通用逻辑 - 不想手动写类型校验函数的场景,可以搭配zod这类运行时类型校验库使用,能大幅减少重复代码量
内容的提问来源于stack exchange,提问作者Solaris
相关产品推荐
相关产品推荐

