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

如何用TypeScript为Store选择器函数的返回值标注类型?

问题分析与解决方案

问题根源

  1. Listener类型约束过紧:原定义的Listener<TStore>强制selectorFn返回完整的TStore类型,但实际选择器需要返回Store的部分数据(比如单个字段的number类型),导致类型不匹配。
  2. useStore泛型无关联约束:直接给useStore添加泛型T时,TypeScript无法确认T与TStore的派生关系,因此抛出"任意类型可能与TStore无关"的错误。

修正方案

1. 调整Listener类型,支持任意返回值

将selectorFn的返回类型改为unknown,兼容所有可能的选择器返回结果:

type Listener<TStore> = {
  selectorFn: (store: TStore) => unknown
}

2. 正确标注useStore的泛型

给useStore的泛型T设置默认值为TStore(对应不传选择器时返回整个Store的场景),同时明确选择器函数的类型为(store: TStore) => T:

function useStore<T = TStore>(selectorFn: (store: TStore) => T = (store) => store as T): T {
  const listener = {
    selectorFn,
    // 其他内容
  }
  listeners.add(listener)
  return selectorFn(store)
}

这里的as T是安全断言:默认选择器返回完整的TStore,而泛型T的默认值就是TStore,类型完全匹配。


完整修正代码

type Listener<TStore> = {
  selectorFn: (store: TStore) => unknown
}

function createStore<TStore>(store: TStore) {
  const listeners = new Set<Listener<TStore>>()

  function useStore<T = TStore>(selectorFn: (store: TStore) => T = (store) => store as T): T {
    const listener = {
      selectorFn,
      // 其他内容
    }
    listeners.add(listener)
    return selectorFn(store)
  }

  return [useStore]
}

const [useStore] = createStore({
  count: 0,
  input: ''
})

function DisplayStore() {
  const count = useStore((store) => store.count) // 类型正确,count为number
  const fullStore = useStore() // 类型正确,为{count: number; input: string}
}

补充说明

如果后续需要在触发监听时处理选择器的返回值,可以通过类型守卫将unknown类型转换为具体类型;泛型T = TStore确保了不传选择器时,默认返回完整Store的类型,符合预期行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:12:08