如何用单个TypeScript类型守卫函数处理多类型可选值数组?
针对多变量(任意长度/类型)的非空类型守卫方案
你遇到的问题是TypeScript类型系统的限制:类型断言不能直接引用剩余参数。不过可以通过泛型元组+映射类型实现单个函数,处理任意长度、不同类型变量的非空断言,同时保留每个变量的原始类型信息。
解决方案代码
function assertAllValues<T extends readonly (unknown | null | undefined)[]>( ...values: T ): values is { [K in keyof T]: Exclude<T[K], null | undefined> } { // 检查所有参数都不为 null/undefined return values.every(value => value != null); }
使用示例
// 模拟返回未知值的函数 function unknown1(): string | null { return Math.random() > 0.5 ? "hello" : null; } function unknown2(): number | null { return Math.random() > 0.5 ? 123 : null; } function unknown3(): boolean | undefined { return Math.random() > 0.5 ? true : undefined; } const value1: string | null = unknown1(); const value2: number | null = unknown2(); const value3: boolean | undefined = unknown3(); // 断言多个变量非空 if (assertAllValues(value1, value2, value3)) { // 此处TypeScript自动收窄类型: // value1: string, value2: number, value3: boolean console.log(value1.toUpperCase(), value2.toFixed(2), value3); }
原理说明
- 泛型元组约束:
T extends readonly (unknown | null | undefined)[]让函数接收任意长度的参数,每个参数可以是unknown、null或undefined,覆盖所有非空断言场景。 - 映射类型收窄:
{ [K in keyof T]: Exclude<T[K], null | undefined> }遍历元组的每个索引,排除对应元素类型中的null和undefined,生成每个元素都非空的新元组类型。 - 绕过语法限制:断言类型基于输入元组
T的映射,而非直接引用剩余参数的数组类型,因此符合TypeScript的语法规则。
这个方案支持任意数量的参数,能准确保留每个参数的原始类型(比如string | null收窄为string,number | null收窄为number),完全匹配你的需求。
内容的提问来源于stack exchange,提问作者James Jenkinson
相关产品推荐
相关产品推荐

