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

如何让TypeScript自动推断handle函数泛型类型无需显式声明

解决TypeScript泛型自动推断问题:关联版本键与处理函数的类型匹配

问题核心

当前handle函数必须显式指定OtherProps和Result泛型才能正常工作,根源在于:

  • 原Handlers类型强制所有处理函数返回统一的Result,且OtherProps全局一致,无法适配不同处理函数返回不同类型的场景(比如multipliers中alpha返回string、beta返回number)。
  • execute回调的泛型约束过于宽泛,TypeScript无法将props.value的类型与对应handler的value参数类型关联起来。

解决方案

通过重构类型定义和handle函数的泛型结构,让TypeScript自动从处理函数字典中推断公共OtherProps和每个键对应的返回类型:

1. 重构类型定义

调整Handler和Handlers的定义,保留每个键对应的返回类型,同时提取公共的OtherProps:

export interface VersionDictionary {
  alpha: string
  beta: number
}
export type VersionKey = keyof VersionDictionary

// 单个处理函数:保留Key对应的value类型与自定义返回类型
export type Handler<Key extends VersionKey, OtherProps, Result> = (
  props: OtherProps & { value: VersionDictionary[Key] }
) => Result

// 处理函数字典:每个Key对应独立的Handler类型,允许不同返回值
export type Handlers<OtherProps, ResultMap extends Record<VersionKey, unknown>> = {
  [Key in VersionKey]: Handler<Key, OtherProps, ResultMap[Key]>
}

export interface Matched<Key extends VersionKey, OtherProps, Result> {
  handler: Handler<Key, OtherProps, Result>
  value: VersionDictionary[Key]
}

2. 修改match和handle函数泛型

调整泛型参数,适配不同返回类型,让TypeScript自动推断类型:

function match<OtherProps, Key extends VersionKey, Result>(
  data: Partial<VersionDictionary>,
  handlers: Handlers<OtherProps, Record<VersionKey, Result>>,
  key: Key
): Matched<Key, OtherProps, Result> | undefined {
  const value = data[key]
  if (value == null) return undefined
  const handler = handlers[key]
  return { handler, value }
}

// 通过ResultMap捕获每个Key的返回类型,自动推断OtherProps
function handle<OtherProps, ResultMap extends Record<VersionKey, unknown>>(
  dictionary: Partial<VersionDictionary>,
  handlers: Handlers<OtherProps, ResultMap>,
  execute: <Key extends VersionKey>(
    props: {
      value: VersionDictionary[Key]
      handler: Handler<Key, OtherProps, ResultMap[Key]>
    }
  ) => ResultMap[Key]
): ResultMap[keyof ResultMap] {
  let key: VersionKey
  for (key in handlers) {
    const matched = match(dictionary, handlers as Handlers<OtherProps, Record<VersionKey, ResultMap[typeof key]>>, key)
    if (matched == null) continue
    return execute({ value: matched.value, handler: matched.handler })
  }
  throw new Error('Unknown key')
}

3. 验证示例代码

现在无需显式指定泛型,TypeScript能自动推断类型且无报错:

const alphaData = { alpha: 'hello' }
const betaData = { beta: 4 }

const labelers = {
  alpha: (props: { value: string, label: string }) => `${props.label}: ${props.value}`,
  beta: (props: { value: number, label: string }) => `${props.label} + 1: ${props.value + 1}`
}

const label = `Test (${new Date().toISOString()})`

// 自动推断OtherProps为{ label: string },Result为string
handle(alphaData, labelers, (props) => props.handler({ value: props.value, label }))
handle(betaData, labelers, (props) => props.handler({ value: props.value, label }))

const multipliers = {
  alpha: (props: { value: string, count: number }) => props.value.repeat(props.count),
  beta: (props: { value: number, count: number }) => props.value * props.count
}
const count = 5

// 自动推断OtherProps为{ count: number },Result为string | number
handle(alphaData, multipliers, (props) => props.handler({ value: props.value, count }))
handle(betaData, multipliers, (props) => props.handler({ value: props.value, count }))

关键改动说明

  • Handlers类型重构:新增ResultMap泛型,允许每个版本键对应不同返回类型,打破原定义中所有处理函数返回同类型的限制。
  • handle函数泛型调整:通过ResultMap捕获每个键的返回类型,让TypeScript自动从处理函数字典推断公共OtherProps和各键返回值类型。
  • execute回调约束强化:明确handler返回类型为ResultMap[Key],确保props.value与handler的value参数类型严格匹配,解决类型不兼容错误。

内容的提问来源于stack exchange,提问作者David Y. Stephenson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:44:55