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

如何实现验证元组每个项均已定义的Type Guard?

实现支持元组的非空数组类型守卫

原Stack Overflow上《Type guard for verifying that each item of an array is defined》的采纳方案无法处理元组场景,原方案代码如下:

function isDefined<T> (value: NonNullable<T> | undefined | null): value is NonNullable<T> {
  return value !== null && value !== undefined
}

function isEachItemDefined<T> (value: ReadonlyArray<NonNullable<T> | undefined | null>): value is ReadonlyArray<NonNullable<T>> {
  return value.every(isDefined)
}

在如下元组场景中,该守卫无法正确推导元素类型:

type Test = { value: number };
const array: readonly [Test | null, Test | null] = [null, null];

if (isEachItemDefined(array)) {
  const [val1, val2] = array; // val1、val2仍为Test | null,不符合预期
}

要实现同时支持可变数组、只读数组、元组的非空类型守卫,需利用TypeScript的映射类型处理数组/元组的每个元素,而非统一转为ReadonlyArray。具体实现如下:

// 基础非空判断守卫
function isDefined<T>(value: T | null | undefined): value is NonNullable<T> {
  return value !== null && value !== undefined;
}

// 支持元组的数组非空守卫
function isEachItemDefined<T extends readonly (unknown | null | undefined)[]>(
  value: T
): value is { [K in keyof T]: NonNullable<T[K]> } {
  return value.every(isDefined);
}

效果验证

元组场景

type Test = { value: number };
const array: readonly [Test | null, Test | null] = [{ value: 1 }, { value: 2 }];

if (isEachItemDefined(array)) {
  const [val1, val2] = array; // val1、val2类型均为Test,符合预期
}

普通数组场景

const normalArray: (Test | null)[] = [{ value: 3 }, { value: 4 }];
if (isEachItemDefined(normalArray)) {
  normalArray.forEach(item => {
    console.log(item.value); // item类型为Test,无类型报错
  });
}

原理说明:通过泛型T extends readonly (unknown | null | undefined)[]约束输入为任意数组/元组,再用映射类型{ [K in keyof T]: NonNullable<T[K]> }移除每个元素的null和undefined类型,让TypeScript能正确推导元组每个位置的具体类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:24:59