打字稿:在React中使用defaultProps编写包装组件的HOC

时间:2019-02-18 22:06:33

标签: reactjs typescript react-redux

尝试编写多个HOC(带有compose func)似乎完全失去了props注释,好像制作一个不会丢失它的适当HOC一样,包装组件的默认(因此是可选的)props不够棘手。

找到了一些不错的解决方法,以使HOC利用JSX.LibraryManagedAttributes别名保留包装组件的可选道具:

import React from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

// wrapper
export interface WithThemeProps {
  theme: string;
}

interface WrapperProps {
  foo: string;
}

function withTheme<
  C extends React.ComponentType<React.ComponentProps<C> & WithThemeProps>,
  ResolvedProps = JSX.LibraryManagedAttributes<C, Omit<React.ComponentProps<C>, keyof WithThemeProps>>
>(component: C) {
  return connect<WithThemeProps, void, WrapperProps & ResolvedProps>(() => ({
    theme: 'theme',
  }))(component as React.ComponentType);
}

// component with default props
interface Props extends WithThemeProps {
  message: string;
  required: string;
}

class Component extends React.Component<Props> {
  static defaultProps = {
    message: '',
  };

  render() {
    return <div />;
  }
}

// usage
const Wrapped = withTheme(Component);
const el = <Wrapped required="r" foo="f" />; // works

const Composed = compose(withTheme)(Component);
const HeavilyComposed = compose( withTheme, withTheme )(Component);

const x = <Composed required="r" foo="f" />; // wrapped works
const y = <HeavilyComposed required="r" foo="f" />; // error, props are lost altogether

我也遇到过an interesting idea来为该特定场景建模compose函数。通过对原始答案进行一些调整,可以保留所有道具,但也使它们成为必需,这不是我期望的:

const HeavilyComposed = compose( withTheme, withTheme )(Component);
// Type '{ required: string; foo: string; }' is missing the
// following properties from type 'Props': message, theme
const y = <HeavilyComposed required="r" foo="f" />; 

declare function compose<A, R, R2>(
  f1: (b: A) => React.ComponentType<R2>,
  f2: (b: A) => React.ComponentType<R>
): <P>(c: React.ComponentType<P>) => React.ComponentType<P & R & R2>;

撰写函数应如何保留可选和省略的道具?

0 个答案:

没有答案