You need to enable JavaScript to run this app. TypeScript:如何用简洁写法实现多值判断并保留类型窄化
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript:如何用简洁写法实现多值判断并保留类型窄化

核心原理

要让if判断触发TypeScript的自动类型收窄,判断逻辑必须是返回类型谓词的类型守卫。原生Array.prototype.includes的类型定义仅返回普通布尔值,不满足类型守卫的要求;同时普通数组会被推断为宽的元素类型(比如string[]而非字面量联合类型),因此无法自动收窄传入值的类型,也就达不到串联多个||的推断效果。

实现方案

1. 通用类型守卫实现

首先写一个可复用的判断函数,兼容所有只读字面量数组的判断场景:

function isOneOf<T extends readonly unknown[]>(
  candidateArr: T,
  targetVal: unknown
): targetVal is T[number] {
  // 内部逻辑直接复用原生includes,无额外运行时开销
  return (candidateArr as readonly unknown[]).includes(targetVal);
}

这个函数的返回值是标准的类型谓词targetVal is T[number],完全符合TypeScript的类型收窄规则。使用时给候选值数组加上as const,让TS把数组推断为精确的只读字面量元组,即可获得和串联||完全一致的推断效果:

// 加as const后,数组的类型为readonly ["a", "b"]
const allowedValues = ["a", "b"] as const;
const str: string = getDynamicStr();

if (isOneOf(allowedValues, str)) {
  // 此处str的类型自动收窄为"a" | "b",和串联||的效果没有差异
}

2. 适配业务场景的优化

针对需要判断接口布尔类型属性名的场景,可以搭配内置映射类型的工具逻辑,自动从接口中提取符合要求的属性名,减少手动维护候选列表的疏漏:

interface Filters {
    isPromo?: boolean,
    isFreeShipping?: boolean,
    isNew?: boolean,
    isInStock?: boolean,
    title?: string
}

// 工具类型:提取接口中所有值类型为boolean的属性名
type BooleanPropKeys<T> = {
  [K in keyof T]-?: T[K] extends boolean ? K : never
}[keyof T];

// 自动推导的类型为 "isPromo" | "isFreeShipping" | "isNew" | "isInStock"
type FilterBooleanKey = BooleanPropKeys<Filters>;

// 候选值数组:TS会自动约束数组元素必须是上述合法的布尔属性名,写错直接触发编译报错
const booleanFilterKeys: FilterBooleanKey[] = [
  "isPromo",
  "isFreeShipping",
  "isNew",
  "isInStock"
];

let filters: Filters = {};

for (const filterValuePair of location.search.split("&")) {
    const [urlFilter, value] = filterValuePair.split("=");
    // 调用自定义的isOneOf做判断,类型收窄效果和串联多个||完全一致
    if (isOneOf(booleanFilterKeys, urlFilter)) {
        // 此处urlFilter的类型自动收窄为四个布尔属性名的联合类型
        // 给filters赋值时不会出现类型不匹配的编译错误
        filters[urlFilter] = Boolean(value);
    }
}
注意事项
  • 候选数组如果不加as const声明,TS会把数组元素推断为宽的string类型,最终判断时无法得到精确的字面量类型
  • 自定义的isOneOf函数已做只读数组兼容,不需要对用as const生成的元组做额外类型转换
  • 整个方案的运行时判断逻辑和原生includes完全一致,没有额外性能损耗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 19:45:02