流类型高阶组件(HOC)道具类型保存

时间:2017-03-10 21:32:00

标签: javascript reactjs flowtype

我在这个人的头上靠在墙上。我试图将flowtype合并到一些反应项目中。在大多数情况下,打字似乎很有效。但是,我正在使用一个库(react-jss),它使用HOC将样式表类注入到组件中。问题是这个模块没有流量类型,所以它会消除我组件上的任何道具验证,因为我的所有组件都被这个HOC包裹。

我已经能够根据我看到的一些github isuses添加一些打字,所以至少我知道我从react-jss HOC获得了一个组件,但是这个新组件没有与之关联的道具。流程的观点,所以我没有因为未能提供错误类型的必需道具或道具而获得错误(消除了流程的许多好处)。这是我复制粘贴的内容,以获得基本的react-jss HOC定义:

declare type FunctionComponent<A> = (props: A) => ?React$Element<any>;

declare type ClassComponent<D, A, S> = Class<React$Component<D, A, S>>;

declare type Component<A> = FunctionComponent<A> | ClassComponent<any, A, any>;

declare type Fn1<A, B> = (a: A) => B;

declare type HOC<A, B> = Fn1<Component<A>, Component<B>>;

declare module 'react-jss' {
  declare module.exports: (styleSheet: Object) => HOC<A, B>;
}

请记住react-jss默认导出(injectStyles)的rought签名是这样的:

function injectStyles(styleSheet: AnObject)(Component: ReactComponent<Props>): ReactComponent<PropsWithStyleClasses>

1 个答案:

答案 0 :(得分:1)

您可以尝试以下定义:

declare module 'react-jss' {
  // Export these
  declare type FunctionComponent<P> = (props: P) => ?React$Element<any>;
  declare type ClassComponent<D, P, S> = Class<React$Component<D, P, S>>;

  declare type Klasses<CSS> = {
    [classname: $Keys<CSS>]: string,
  };

  declare type JSSProps<CSS> = {
    classes: Klasses<CSS>,
    sheet: {
      attached: boolean,
      classes: Klasses<CSS>,
      deployed: boolean,
      linked: boolean,
      options: Object,
      renderer: mixed,
      rules: mixed,
    },
  };

  declare type Injector = {
    <Props, State, DefaultProps, CSS>(component: ClassComponent<DefaultProps, Props, State>): ClassComponent<DefaultProps, $Diff<Props, JSSProps<CSS>>, void>;
    <Props, CSS>(component: FunctionComponent<Props>): FunctionComponent<$Diff<Props, JSSProps<CSS>>>;
  };

  declare function exports<Props, State, DefaultProps, CSS>(
    CSS: CSS,
  ): Injector
}

请注意,导入注入的组件时,流会出现一些问题。使用课程时一切正常:

// Test.js
class Test extends React.Component<void, { text: string }, void> {
    ...
}
export const StyledTest = injectSheet(style)(Test)

// Main.js
...
render() {
    return <StyledTest /> // ERROR here, missing `text` prop
}

但是对于功能组件,您需要明确键入它:

// Test.js
const Test = (props: { text: string }) => {
    ...
}
export const StyledTest: FunctionComponent<{ text: string }> = injectSheet(style)(Test) // Explicitly type this

// Main.js
...
render() {
     return <StyledTest /> // ERROR here, so it works!
}

我不确定这些问题是否已在流程中修复,但此设置对我来说很好。