如何用TypeScript类型谓词正确校验数组元素为Record类型?
解决TypeScript数组类型守卫的"Object is possibly null"问题
首先,先确认单个元素类型守卫isRecord的正确实现,确保它能准确排除null并识别纯对象类型:
function isRecord(value: unknown): value is Record<string, any> { // 排除null、数组,确保是纯对象 return value !== null && typeof value === 'object' && !Array.isArray(value); }
针对数组的校验,你需要编写同时验证数组结构和每个元素类型的类型守卫,TypeScript才能正确缩小数组内元素的类型,避免“Object is possibly null”错误。以下是几种场景的正确实现:
1. 基础数组类型守卫
判断输入是否为Record<string, any>[]类型:
function isRecordArray(value: unknown): value is Record<string, any>[] { // 先确认是数组,再校验每个元素都符合isRecord规则 return Array.isArray(value) && value.every(isRecord); } // 使用示例 function handleRecords(input: unknown) { if (isRecordArray(input)) { input.forEach(record => { // 此处TypeScript会正确识别record为非null的Record<string, any> console.log(record.userId); }); } }
2. 剩余参数的类型校验
如果需要校验函数剩余参数是否全为Record类型:
function areRecords(...values: unknown[]): values is Record<string, any>[] { return values.every(isRecord); } // 使用示例 function processMultipleInputs(...inputs: unknown[]) { if (areRecords(...inputs)) { inputs.forEach(item => { console.log(item.data); }); } }
为什么之前的写法会报错?
- 若仅判断
Array.isArray(value)而不校验元素,TypeScript仅知道这是unknown[],每个元素仍可能为null或其他类型; - 仅返回布尔值而不用类型谓词(
value is ...),TypeScript无法进行类型缩小; - 剩余参数场景下,若未通过
every校验每个元素,类型守卫无法覆盖所有元素的非空断言。
内容的提问来源于stack exchange,提问作者Galdor
相关产品推荐
相关产品推荐

