如何在TypeScript中为高阶类组件正确设置类型?

时间:2018-02-19 16:06:27

标签: reactjs typescript

我有一个实用程序函数,它接受一个(现在未使用的)选项参数并返回一个更高阶的组件包装函数。

如何在组件上正确设置类型,以使包装组件的用户看到基础包装组件的类型以及withAppContext高阶组件中的其他上下文类型?

type AppContext = {
  id: string;
};

const withAppContext = (opts) => {
  const hoc = WrappedComponent => {
    class WithAppContext extends React.Component<any, any> {
      static contextTypes = {
        appContext: PropTypes.shape({
          id: PropTypes.string,
        }),
      };

      context: AppContext;

      render() {
        return React.createElement(WrappedComponent, {
          ...this.props,
          ...this.context
        });
      }
    }
    return WithAppContext;
  };
  return hoc;
};

仅延伸React.Component(没有<any, any>)时,我会抱怨IntrinsicAttributes不包含我要传递的道具(即我似乎无法通过通过道具到包裹的组件):

error TS2339: Property 'onClick' does not exist on type
    'IntrinsicAttributes
    & IntrinsicClassAttributes<WithCustomerContext>
    & Readonly<{ children?: React...'.

1 个答案:

答案 0 :(得分:0)

您的hoc函数应该是通用函数,以便根据用法推断属性:

const withAppContext = function (opts) {

    function hoc <P>(WrappedComponent: React.StatelessComponent<P>) : React.ComponentClass<P>
    function hoc <P, T extends React.Component<P, React.ComponentState>, C extends React.ComponentClass<P>>(WrappedComponent: React.ClassType<P, T, C>) : React.ComponentClass<P>
    function hoc <P>(WrappedComponent: any ) : React.ComponentClass<P>
    {
        class WithAppContext extends React.Component<P> {

            context: AppContext;

            render() {
                return React.createElement(WrappedComponent, Object.assign({}, this.props, this.context));
            }
        }
        return WithAppContext;
    };
    return hoc;
}

class MyComponent extends React.Component<{ prop: string }>{

}
const MyComponentWithContext = withAppContext({})(MyComponent);
let d = <MyComponentWithContext prop =""  />



let GreeterComponent = function (props: {name: string, greeting: string}){
    return <div>{props.greeting} {props.name}!</div> 
}
const GreeterComponentContext = withAppContext({})(GreeterComponent);
let d2 = <GreeterComponentContext  name="" greeting=""  />