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

如何让封装的Redux useSelector Hook的泛型R自动从回调返回值推导类型?

如何让封装的Redux useSelector Hook的泛型R自动从回调返回值推导类型?

当然可以实现!你现在的问题出在泛型参数的定义上——原来的代码把R作为一个需要显式指定的泛型参数,但实际上我们可以让TypeScript自动从你传入的selector回调的返回值里推断出R的类型,完全不用手动写。

具体修改方案

我们只需要调整useAppSelector的泛型定义,去掉显式的R参数,让TypeScript自动推导selector的返回类型就行。下面是两种可行的修改方式:

方式1:利用ReturnType自动推断返回类型

export const useAppSelector = <T extends AbstractContract>(
  // 不用显式声明R,TypeScript会自动从selector的返回值推断
  selector: (container?: ContractContainer<T>) => unknown,
  equalFnOptions?: EqualityFn<unknown>
): ReturnType<typeof selector> => {
  return useSelector<AppState<T>, ReturnType<typeof selector>>((state) => {
    if (state.data.activeObject) {
      const container = getContainerFromCache(
        state.data.contractCache,
        state.data.activeContract
      );
      // 用ReturnType断言类型,确保和selector返回值匹配
      return selector(container) as ReturnType<typeof selector>;
    }
    // 当没有activeObject时,返回符合selector返回类型的默认值
    return undefined as ReturnType<typeof selector>;
  }, equalFnOptions as EqualityFn<ReturnType<typeof selector>>);
};

方式2:让R从selector参数自动推导

export const useAppSelector = <T extends AbstractContract, R>(
  selector: (container: ContractContainer<T>) => R,
  equalFnOptions?: EqualityFn<R | undefined>
): R | undefined => {
  return useSelector<AppState<T>, R | undefined>((state) => {
    if (state.data.activeObject) {
      const container = getContainerFromCache(
        state.data.contractCache,
        state.data.activeContract
      );
      // 确保container存在时才调用selector,避免undefined报错
      return container ? selector(container) : undefined;
    }
    return undefined;
  }, equalFnOptions);
};

调用方式不变,类型自动生效

修改完Hook之后,你原来的调用代码完全不用改,TypeScript会自动帮你推断出owner的类型:

type CarContract = { id: number; owner: Person; }
const owner = useAppSelector<CarContract>(
  (container) => container.contract.owner
);
// 现在owner的类型会被自动推断为Person(或Person | undefined,取决于你是否处理了container为undefined的情况)

为什么这样能行?

原来的代码里,R是作为独立的泛型参数需要手动指定的,但调整后,R会被TypeScript从selector回调的返回值里自动推导出来——当你传入<CarContract>时,TypeScript先确定container的类型是ContractContainer<CarContract>,再结合你写的container.contract.owner,就能直接推断出返回值是Person类型。

如果你的selector需要处理container可能为undefined的情况,比如用可选链container?.contract.owner,那TypeScript也会自动把owner的类型推断为Person | undefined,非常贴合实际场景。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 11:57:58