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

TypeScript:依赖内部属性的泛型配置数组类型推断问题

解决NgRx Effects通用工厂函数的类型推断问题

问题根源

  • 初始版本用单个泛型AC extends ActionCreator,要求数组中所有Config的action必须是同一类型,导致多类型action传入时报错。
  • 修改为AC extends ActionCreator[]后,Config<AC[number]>会将所有ActionCreator合并为联合类型,映射函数的参数变成联合类型的返回值,TypeScript无法为每个数组元素单独推断精确类型,只能得到宽泛的Object类型。

解决方案:使用元组泛型+映射类型

通过让泛型推导传入的数组为元组,并对元组的每个元素单独应用Config类型,确保每个mapping函数能精确对应其action的返回类型。

修改后的代码实现

// NgRx导入
import { ActionCreator } from '@ngrx/store';
import { createActionGroup, props } from '@ngrx/store';

// 测试用ActionGroup
export const featureActions = createActionGroup({
  source: 'MyGroup',
  events: {
    'Update Entity': props<{ data: { updateName: string } }>(),
    'Delete Entity': props<{ data: { deleteName: string } }>(),
  },
});

// Config类型定义(保持不变)
export type Config<AC extends ActionCreator> = {
  action: AC;
  mapping: (data: ReturnType<AC>) => string;
};

// 优化后的工厂函数
export function createMyEffects<AC extends ActionCreator[]>(
  effects: { [K in keyof AC]: Config<AC[K]> }
) {
  console.log(effects);
}

// 调用示例:类型推断正常,无报错
createMyEffects([
  {
    action: featureActions.updateEntity,
    mapping: (updateData) => updateData.data.updateName, // updateData类型精确为ReturnType<typeof featureActions.updateEntity>
  },
  {
    action: featureActions.deleteEntity,
    mapping: (deleteData) => deleteData.data.deleteName, // deleteData类型精确为ReturnType<typeof featureActions.deleteEntity>
  },
]);

原理说明

  • 泛型AC extends ActionCreator[]会提示TypeScript将传入的数组字面量推断为元组类型(而非普通数组),元组中每个元素对应不同的ActionCreator类型。
  • 映射类型{ [K in keyof AC]: Config<AC[K]> }遍历元组的每个索引K,为每个位置生成对应的Config<AC[K]>类型,确保每个元素的mapping参数类型与自身action的返回类型严格绑定。

这样既解决了多类型action传入的类型冲突问题,又保留了每个mapping函数参数的精确类型推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:25:17