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

如何在TypeScript中实现数组联合类型的类型收窄?

TypeScript联合数组类型收窄方案

对于定义的联合类型type MyUnion = string[] | number[],直接检查数组元素的typeof无法收窄整个数组的类型——因为TypeScript不会自动将单个元素的类型推断关联到整个数组的类型。以下是几种可行的收窄方案:

1. 自定义类型守卫(类型谓词)

这是最常用且直观的方案,通过自定义函数明确告诉TypeScript如何判断数组的具体类型:

type MyUnion = string[] | number[];

// 判断是否为字符串数组
function isStringArray(arr: MyUnion): arr is string[] {
    // 基础判断:数组非空且首元素为字符串
    return arr.length > 0 && typeof arr[0] === "string";
    // 更严谨的判断:检查所有元素(适合需要确保全量类型的场景)
    // return arr.every(item => typeof item === "string");
}

// 判断是否为数字数组
function isNumberArray(arr: MyUnion): arr is number[] {
    return arr.length > 0 && typeof arr[0] === "number";
    // 更严谨版本
    // return arr.every(item => typeof item === "number");
}

const arr: MyUnion = ["hello", "typescript"];
if (isStringArray(arr)) {
    // 此处arr类型已收窄为string[]
    console.log(arr.map(s => s.toUpperCase()));
} else {
    // 此处arr类型已收窄为number[]
    console.log(arr.map(n => n * 2));
}

2. 结合every与内联类型谓词

如果不想单独定义函数,可以直接在every方法中使用内联类型谓词完成收窄:

type MyUnion = string[] | number[];

const arr: MyUnion = [1, 2, 3];
if (arr.every((item): item is string => typeof item === "string")) {
    // arr类型收窄为string[]
    arr.push("new string");
} else {
    // arr类型收窄为number[]
    arr.push(4);
}

注意事项

  • 若数组为空([]),上述基于元素的判断逻辑会进入else分支,需根据业务场景单独处理空数组的情况;
  • 选择基础判断(仅检查首元素)还是全量检查(every遍历),取决于你对数组类型安全性的要求——全量检查更严谨但性能略低,基础判断适合确定数组元素类型统一的场景。

内容的提问来源于stack exchange,提问作者Lars Nyström

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:22:24