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

如何在TypeScript中无需复制泛型参数改造通用函数?

实现带副作用的createSlice高阶封装(无需复制泛型参数)

核心思路是用高阶函数包装原createSlice,借助TypeScript的泛型推断能力直接复用原函数的所有泛型定义,完全避免手动复制参数类型的繁琐操作,还能解决原函数内部类型未导出的问题。

步骤1:获取原createSlice的类型签名

不管原createSlice的泛型有多复杂,我们不需要手动写出来,直接通过typeof提取它的类型:

// 直接获取原函数的类型,无需关心内部泛型细节
type BaseCreateSlice = typeof createSlice;

步骤2:定义副作用的类型约定

根据需求定义副作用的结构,这里以接收slice名称和状态为例:

// 副作用函数的类型,自动关联slice的状态类型
type SliceSideEffects<State> = Record<string, (sliceName: string, state: State) => void | Promise<void>>;

步骤3:实现高阶封装函数

通过泛型约束和类型推断,让包装函数自动继承原createSlice的所有泛型参数:

function createSliceWithSideEffects(baseCreateSlice: BaseCreateSlice) {
  return <Args extends Parameters<BaseCreateSlice>>(
    sliceConfig: Args[0] & {
      // 自动推断原slice的初始状态类型
      sideEffects?: SliceSideEffects<ReturnType<Args[0]['getInitialState']>>
    }
  ) => {
    // 调用原函数创建基础slice
    const baseSlice = baseCreateSlice(sliceConfig as Args[0]);
    const initialState = baseSlice.getInitialState();

    // 添加副作用执行方法
    const runSideEffects = async () => {
      if (!sliceConfig.sideEffects) return;
      for (const effect of Object.values(sliceConfig.sideEffects)) {
        await effect(baseSlice.name, initialState);
      }
    };

    // 返回合并了副作用能力的slice实例
    return { ...baseSlice, runSideEffects };
  };
}

使用示例

用包装后的函数创建slice,完全继承原createSlice的类型提示,同时支持副作用配置:

// 包装原createSlice得到带副作用的版本
const enhancedCreateSlice = createSliceWithSideEffects(createSlice);

// 创建带副作用的counter slice,类型自动匹配
const counterSlice = enhancedCreateSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value++ },
  },
  sideEffects: {
    logInit: (name, state) => {
      console.log(`[${name}] 初始值: ${state.value}`);
    },
    fetchRemoteData: async (name) => {
      // 模拟异步副作用操作
      const res = await fetch(`/api/${name}/init-data`);
      const data = await res.json();
      // 可结合dispatch更新状态,示例省略
    }
  }
});

// 执行所有副作用
counterSlice.runSideEffects();

方案优势

  • 零重复泛型:完全依赖TypeScript的类型推断,不需要手动复制原createSlice的任何泛型参数
  • 兼容未导出类型:即使原createSlice的内部类型(比如Slice、State)没导出,也能通过Parameters和ReturnType自动推断出来
  • 低维护成本:原createSlice的泛型或参数更新时,封装函数会自动同步,不需要手动修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:22:14