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

TypeScript泛型函数如何从入参自动推断类型约束数组成员

解决方案

原实现的类型漏洞来自TypeScript泛型的默认推导规则:泛型T会同时从values数组、value两个入参位置收集候选类型,最终取联合类型作为T的实际类型。因此当你向数组传入任意字符串时,该字符串会被自动加入T的联合类型范围,自然不会触发类型报错。

要实现无需手动传泛型、自动从value参数推导类型并校验数组元素,只需要阻止TS从第一个values参数位置推导泛型T,让T的类型完全由第二个value参数决定即可。


TS 5.4+ 直接使用内置工具类型

TS 5.4 正式内置了NoInfer工具类型,作用就是标记指定类型位置不参与泛型推导,仅做类型校验,直接修改函数定义即可生效:

export function isValueInArray<T extends string>(
  values: NoInfer<T>[],
  value: T | undefined
) {
  return value ? values.includes(value) : false;
}

TS 5.4 以下版本兼容写法

如果使用的TS版本低于5.4,可以手动实现等价的NoInfer类型,配合原函数使用即可:

// 低版本等价NoInfer实现
type NoInfer<T> = [T][T extends any ? 0 : never];

export function isValueInArray<T extends string>(
  values: NoInfer<T>[],
  value: T | undefined
) {
  return value ? values.includes(value) : false;
}

实际效果

修改后所有场景都会自动完成类型推导和校验,不需要手动传入泛型参数:

  • 输入数组元素时,会自动根据value的类型给出合法值补全提示
  • 传入不在value类型范围内的数组元素时,TS会直接抛出类型错误
export type Status = 'OPEN' | 'CANCELED' | 'ACCEPTED' | 'INVALIDATED';

declare const buyNowStatus: Status;
// 合法传参,无报错
const isValid = isValueInArray(['OPEN'], buyNowStatus);
// 非法传参,TS报错:类型'"ANY"'的参数不能赋给类型'Status'的参数
const shouldBeInvalid = isValueInArray(['OPEN', 'ANY'], buyNowStatus);

function checkStatus(status: Status) {
  // 非法传参,TS报错:类型'"ANY"'的参数不能赋给类型'Status'的参数
  return isValueInArray(['ANY'], status);
}

边界情况说明

当传入的value为undefined时,因为没有可用于推导T的类型来源,T会回退到string约束,数组可以传入任意字符串。这个行为和原函数逻辑完全一致:value为undefined时函数固定返回false,不需要校验数组元素类型,不会产生逻辑问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:19:06