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

如何在react-redux的connect中传递泛型参数

如何在react-redux的connect中传递泛型参数

我遇到了这样的问题:当用react-redux的connect包装一个带泛型参数的React组件后,泛型参数会丢失——直接使用原组件时,类型推断和手动指定泛型都正常,但包装后的Connected组件既无法自动推断泛型类型(handler参数会被推断为unknown),手动指定泛型参数时还会报TS2558错误(提示不需要类型参数)。

问题复现代码

import { render } from '@testing-library/react-native';
import React, { Component } from 'react';
import { Provider, connect } from 'react-redux';
import { createStore } from 'redux';

type Props<T> = {
  data: T;
  handler: (data: T) => void;
};

class Unconnected<T> extends Component<Props<T>> {
  render() {
    this.props.handler(this.props.data);
    return null;
  }
}

// 原组件测试完全正常
describe('Unconnected', () => {
  it('inferred', () => {
    const callback = jest.fn();
    render(
      <Unconnected data="hello" handler={(data: string) => callback(data)} />
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });

  it('specified', () => {
    const callback = jest.fn();
    render(
      <Unconnected<string> data="hello" handler={(data: string) => callback(data)} />
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });
});

// 包装后的Connected组件出现类型错误
describe('Connected', () => {
  const store = createStore(() => {});
  const Connected = connect()(Unconnected);

  it('inferred', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected data="hello" handler={(data: string) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });

  it('specified', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected<string> data="hello" handler={(data: string) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });
});

错误原因

connect默认的类型定义会自动将泛型组件转换为非泛型组件类型,导致原组件的泛型参数T无法被保留和传递给包装后的组件。


解决方案

我们可以通过类型断言或手动定义泛型组件类型的方式,让Connected组件保留原组件的泛型参数,以下是三种实用方案:

方案1:类型断言(简单快速)

直接将connect返回的组件断言为原组件的类型,完整保留原组件的泛型特性,适合无自定义mapStateToProps/mapDispatchToProps的简单场景:

describe('Connected', () => {
  const store = createStore(() => {});
  // 关键:用类型断言保留原组件的泛型类型
  const Connected = connect()(Unconnected) as typeof Unconnected;

  it('inferred', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected data="hello" handler={(data) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });

  it('specified', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected<string> data="hello" handler={(data) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });
});
  • 优点:实现简单,代码改动小
  • 缺点:原组件Props类型变化时,断言不会自动同步,需手动维护

方案2:手动定义泛型组件类型(类型安全)

如果需要更严格的类型检查,可以手动定义Connected组件的泛型类型,合并Redux注入的Props和原组件的泛型Props:

import { connect, ConnectedProps } from 'react-redux';

// 定义你的RootState全局状态类型
type RootState = {};

// 定义mapState/mapDispatch(无自定义逻辑时返回空对象即可)
const mapState = (state: RootState) => ({});
const mapDispatch = {};

// 创建连接器并合并Props类型
const connector = connect(mapState, mapDispatch);
type ConnectedComponentProps<T> = ConnectedProps<typeof connector> & Props<T>;
// 定义Connected为泛型组件
const Connected = connector(Unconnected) as React.ComponentType<ConnectedComponentProps<any>>;

// 测试代码
describe('Connected', () => {
  const store = createStore(() => ({}));

  it('inferred', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected data="hello" handler={(data) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });

  it('specified', () => {
    const callback = jest.fn();
    render(
      <Provider store={store}>
        <Connected<string> data="hello" handler={(data) => callback(data)} />
      </Provider>
    );
    expect(callback).toHaveBeenCalledWith('hello');
  });
});
  • 优点:类型安全,状态或Props变化时TypeScript会及时提示
  • 缺点:需要额外编写类型定义代码,适合复杂业务场景

方案3:泛型连接器(进阶复用)

如果需要在多个泛型组件中复用逻辑,可以创建一个泛型的connect辅助函数:

import { connect } from 'react-redux';

// 定义全局RootState类型
type RootState = {};

// 创建泛型连接器辅助函数
function connectGeneric<TProps>() {
  return connect<{}, {}, TProps, RootState>();
}

// 使用方式
const Connected = connectGeneric<Props<string>>()(Unconnected) as typeof Unconnected;
  • 优点:可在多个泛型组件中复用,减少重复代码
  • 缺点:需要额外封装辅助函数,适合大量泛型组件的项目

总结

核心思路是让connect返回的组件保留原组件的泛型参数,根据项目复杂度和类型安全需求选择合适的方案即可。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:17:59