You need to enable JavaScript to run this app. 如何在TypeScript接口中使用泛型实现dispatch的payload类型正确推断
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript接口中使用泛型实现dispatch的payload类型正确推断

问题解决

错误原因

  1. 你给泛型参数R设置的默认值中,将reducer定义为携带自由泛型<P>的函数,强制要求reducer的payload是未绑定类型的泛型,而实际业务代码中reducer的payload是固定的string[],二者类型不匹配,触发TS2322错误。
  2. TypeScript不支持泛型参数的部分推断:你在调用createModel时仅显式传入了T的类型string[],TS会直接使用R的默认值,不会从你传入的reducers字段自动推导R的实际类型,导致dispatch的payload类型推断失效。

修复方案

采用柯里化拆分泛型参数:第一层接收手动指定的state类型T,第二层完全交给TS自动推断reducers的类型R,和Vue.defineComponent的类型推断实现逻辑一致。修复后的代码如下:

// 柯里化拆分需要手动传入的泛型和自动推断的泛型
export const createModel = <T>() => <R extends Record<string, (prevState: T, payload: any) => T>>(model: {
  state: T;
  reducers: R;
  effects: (dispatch: {
    [K in keyof R]: (
      payload: R[K] extends (prevState: T, payload: infer P) => T ? P : never
    ) => T
  }) => Record<string, () => Promise<void>>;
}) => model;

// 调用时先传入state类型,后续参数自动推导类型
const model = createModel<string[]>()({
  state: ['foo'],
  reducers: {
    update(prevState, payload: string[]) {
      return [
        ...prevState,
        ...payload
      ]
    }
  },
  effects: dispatch => ({
    async request() {
      // 现在dispatch.update的payload会正确推断为string[],无类型错误
      dispatch.update(['bar'])
    }
  })
})

修复后dispatch上的所有方法都会自动提取对应reducer的payload类型,不需要额外手动声明。

TypeScript深入学习资料推荐

书籍

  • 《TypeScript编程》:适合有JavaScript基础的开发者系统学习,内容覆盖从入门到进阶的所有核心语法,实战案例丰富
  • 《Effective TypeScript》:包含62个TS开发的最佳实践,深入讲解类型推断、类型兼容、类型体操的核心原理,适合有基础后提升开发规范
  • 《TypeScript类型编程》:专门聚焦TS类型系统,深度讲解复杂类型、工具类型的实现思路,适合需要写高阶类型工具的开发者阅读

学习建议

  • 首先完整通读TS官方文档的Handbook部分,掌握所有基础和进阶语法特性
  • 练习实现TS内置的工具类型,比如Partial、Pick、ReturnType等,熟悉类型体操的常用技巧
  • 阅读主流开源库的TS类型定义源码,比如Vue、React、Redux的类型实现,学习工业级的类型设计思路

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 22:36:03