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

TypeScript回调函数类型推断异常问题求助

解决TypeScript中computed函数的自动类型推断问题

问题代码片段

interface Store<T> {
  value: T
}

type AnyStore = Store<any>

type StoreValue<T> = T extends Store<infer V> ? V : never

function computed<
  V,
  D extends AnyStore,
  S extends Store<V>
>(
  createStore: (value: V) => S,
  depStore: D,
  compute: (value: StoreValue<D>) => V
): S {
  return createStore(compute(depStore.value))
}

interface MetaStore<T> extends Store<T> {
  meta: {}
}

function meta<T>(value: T): MetaStore<T> {
  return { value, meta: {} }
}

const depStore: Store<number> = { value: 404 }

// 当前类型推断结果:MetaStore<unknown>,预期应为MetaStore<string>
const computedStore = computed(meta, depStore, num => `${num}`)

问题现象

  • 未显式指定compute回调的参数类型时,computedStore被推断为MetaStore<unknown>,不符合预期
  • 显式指定参数类型(如(num: number) => ${num}``)时,类型推断正确,得到MetaStore<string>

解决方案

调整computed函数的泛型参数顺序,将依赖的D(依赖Store的类型)放在最前面,让TypeScript优先推断D的类型,再基于它推导V和S:

function computed<
  D extends AnyStore, // 优先推断依赖Store的类型
  V,
  S extends Store<V>
>(
  createStore: (value: V) => S,
  depStore: D,
  compute: (value: StoreValue<D>) => V
): S {
  return createStore(compute(depStore.value))
}

原理说明

TypeScript的泛型推断是从左到右按顺序进行的。原代码中V在D之前,TypeScript无法先通过depStore推断出D,也就无法用StoreValue<D>确定compute的参数类型,导致V被推断为unknown。

调整泛型顺序后,D先被推断为Store<number>,StoreValue<D>自动解析为number,compute的参数类型明确,V就能正确推断为string,最终S被推导为MetaStore<string>,无需显式指定参数类型。

验证结果

修改后,以下代码的类型推断完全符合预期:

const computedStore = computed(meta, depStore, num => `${num}`)
// 推断结果:const computedStore: MetaStore<string>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:32:47