TypeScript如何通过类型判断实现元组类型收窄,而非仅靠null校验?
问题原因
TypeScript 目前对元组联合的类型收窄,仅会对内置的字面量比较、typeof/instanceof 等原生类型检查做全元组的关联推导,自定义类型守卫暂时不支持这类自动关联推导:
- 你写的
x[0] === null属于内置的字面量相等判断,TS 识别到这个判断可以唯一区分元组联合的两个分支后,会自动把整个x收窄到对应的[null, string]类型,因此x[1]可以正确推断为string。 - 自定义类型守卫
isString(x[0])只会收窄你直接校验的x[0]这个值的类型,不会反向推导整个元组x所属的联合分支,因此x[1]的类型不会被同步收窄。
可行解决方案
方案1:自定义针对整个元组的类型守卫
直接把整个元组作为校验对象,明确声明守卫的返回值是对应的元组类型:
declare function fooB(): [string, number] | [number, string]; // 自定义守卫直接判断整个元组类型 function isFirstStringTuple(x: [string, number] | [number, string]): x is [string, number] { return typeof x[0] === 'string'; } function B() { const x = fooB(); if (isFirstStringTuple(x)) { const y = x[1]; // 此时y会被正确推断为number类型 } }
方案2:先解构元组成员再做类型校验
TypeScript 4.6 及以上版本支持对解构后的联合元组成员做关联收窄,先把元组解构成独立变量再用自定义守卫判断即可:
declare function isString(x: any): x is string; declare function fooB(): [string, number] | [number, string]; function B() { const [a, b] = fooB(); if (isString(a)) { const y = b; // 此时y会被正确推断为number类型 } }
内容的提问来源于stack exchange,提问作者user578895
相关产品推荐
相关产品推荐

