Typescript with React - use HOC on a generic compo

2020-02-26 09:21发布

问题:

I have a generic React component, say like this one:

class Foo<T> extends React.Component<FooProps<T>, FooState> {
    constructor(props: FooProps<T>) {
        super(props);

    render() {
        return <p> The result is {SomeGenericFunction<T>()}</p>;
    }
}

I also have a HOC that looks similar to this one (but is less pointless):

export const withTd = 
    <T extends WithTdProps>(TableElement: React.ComponentType<T>): React.SFC<T> => 
(props: T) => <td><TableElement {...props}/></td>;

But when I use a component like this:

const FooWithTd = withTd(Foo);

There is no way to pass the type argument, as you can do neither withTd(Foo<T>), nor can you do FooWithTd, the type is always wrong. What is the proper way to do that?

EDIT: The problem is that I want to be able to have something like <FooWithTd<number> {...someprops}/> later on, as I don't know the desired type for T in the HOC.

回答1:

Thanks for asking this question. I just figured out a way to specify a type parameter to a component after wrapping it with an HOC and I thought I'd share.

import React from 'react';
import withStyles from '@material-ui/core/styles/withStyles';
import { RemoveProps } from '../helpers/typings';

const styles = {
  // blah
};

interface Props<T> {
  classes: any;
  items: T[];
  getDisplayName: (t: T) => string;
  getKey: (t: T) => string;
  renderItem: (t: T) => React.ReactNode;
}

class GenericComponent<T> extends React.Component<Props<T>, State> {
  render() {
    const { classes, items, getKey, getDisplayName, renderItem } = this.props;

    return (
      <div className={classes.root}>
        {items.map(item => (
          <div className={classes.item} key={getKey(item)}>
            <div>{getDisplayName(item)}</div>
            <div>{renderItem(item)}</div>
          </div>
        ))}
      </div>
    );
  }
}

//