无需显式类型守卫函数,如何收窄string[] | number[]类型?
问题解答
可以在不使用返回T is number[]这类显式类型守卫函数的前提下完成类型收窄,以下是两种可行方案:
方案1:利用Array.every做全类型校验(安全)
通过检查数组首元素类型,再结合every方法验证所有元素的类型一致性,TypeScript会据此将数组收窄为对应的同质数组类型:
declare const arr: string[] | number[]; if (arr.length) { if (typeof arr[0] === 'string' && arr.every(item => typeof item === 'string')) { // arr 已被收窄为 string[] arr.map(x => x.substr(1)); } else if (typeof arr[0] === 'number' && arr.every(item => typeof item === 'number')) { // arr 已被收窄为 number[] arr.map(x => x + 1); } }
这种方法完全安全,通过实际校验确保了数组元素类型统一。
方案2:使用类型断言(简洁且适配当前类型场景)
由于你的数组类型本身是string[] | number[](即元素必然全为string或全为number),可以直接用类型断言跳过TypeScript的检查:
declare const arr: string[] | number[]; if (arr.length) { if (typeof arr[0] === 'string') { (arr as string[]).map(x => x.substr(1)); } else { (arr as number[]).map(x => x + 1); } }
这种方法更简洁,且在你的类型定义下是安全的——因为原类型已经排除了异构数组的可能。
原代码无法收窄类型的原因
TypeScript的控制流分析不会默认将单个数组元素的类型与整个数组的类型绑定。即使你检查了arr[0]是string,它也无法自动推断所有元素都是string(理论上存在首元素为string、后续为number的异构数组可能,尽管你的类型定义排除了这种情况),因此不会主动收窄数组类型。
内容的提问来源于stack exchange,提问作者Qwertiy
相关产品推荐
相关产品推荐

