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

TypeScript如何从对象值提取类型并实现函数入参自动推断

问题根因

  1. 你定义的arr默认被TypeScript推断为{ type: string }[]类型,type属性的类型被自动拓宽为string而非'a' | 'b'字面量联合类型,导致后续infer提取到的类型也是string,无法限制参数范围。
  2. 原有泛型定义没有针对字面量推断做优化,也没有兼容as const生成的只读数组类型。

方案1:加const断言锁死字面量类型

如果数组内容是固定不变的,直接给数组加as const防止类型拓宽,同时调整类型定义兼容只读数组即可:

// as const会把数组锁为只读字面量类型,type属性保持'a'|'b'的联合类型
const arr = [{type:'a'}, {type:'b'}] as const

// 调整TypeFromVal适配只读数组
type TypeFromVal<T> = T extends readonly {type: infer R}[] ? R : never

// 函数泛型也兼容只读数组
function GetType<T extends readonly {type: string}[]>(arr: T, type: TypeFromVal<T>) {
  return arr.find(item => item.type === type)!.type
}

// 调用时会直接报错
GetType(arr, 0) // 类型错误:0不属于 "a" | "b" 联合类型
// 合法调用
GetType(arr, 'a') // 类型校验通过

方案2:调整泛型结构自动推断字面量

如果不想每次都手动加as const,可以拆分泛型参数让TypeScript自动收窄type的类型:

function GetType<T extends string, U extends {type: T}[]>(arr: U, type: T) {
  return arr.find(item => item.type === type)!.type
}

// 不需要加as const也能正确推断
const arr = [{type:'a'}, {type:'b'}]
GetType(arr, 0) // 直接触发类型错误
GetType(arr, 'a') // 校验正常通过

原理说明

  • TypeScript默认定义可变对象/数组时,会把字符串属性的类型拓宽为通用的string类型,as const可以强制把类型锁为最窄的字面量类型
  • 方案2通过先声明单个type的泛型T,再用T约束数组项的type属性,TypeScript会优先从数组实际值推断T的字面量联合类型,不需要额外做类型断言

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:45:03