如何使用条件道具为HOC添加流类型

时间:2018-12-20 09:47:04

标签: flowtype

我正在尝试定义一个HOC,如果满足某些条件,它会添加道具,但是我不知道如何使它工作。

这是一个粗略的例子……

// @flow

import * as React from 'react'

type EnhancedProps = {| addFoo?: boolean |}
type BaseProps = {| foo?: string |}
type HOC =
  | (Component: React.ComponentType<{| foo: string |}>) => React.ComponentType<EnhancedProps & {addFoo: true}>
  | (Component: React.ComponentType<$Diff<BaseProps, { foo: string }>>) => React.ComponentType<EnhancedProps & {addFoo: false}>

const hoc: HOC = (Component) =>
  ({addFoo, ...props}) => {
    if (addFoo) {
      props = {...props, foo: 'Hi'}
    }
    (props: {...EnhancedProps, foo: string})
    return <Component {...props}/>;
  }


const BaseComponent = ({foo}: BaseProps) => `Hello`;

const Enhanced: React.ComponentType<EnhancedProps> = hoc(BaseComponent);

<Enhanced />;
<Enhanced addFoo/>;

您可以在此处的“尝试”页面上查看错误……https://flow.org/try/#0PTAEAEDMBsHsHcBQiCWBbADrATgF1AFSgCGAzqAEoCmxAxvpNrGqAOTY32vK4CeGVUAFEAdgAtiI2lQAmABSYZyAXlABvAD4kZMgGKxYAfgBcoAEYHoNEaA0BfRHwGgAQmSoLYS0Ks2hIBiagpLjYKCIA5rYOToIAEgDyAMI+oIigtqAAFEnMWCJUIrim1HS4AHS5mLAFRQAq-FQAPH4BsKYhYZHRAHwAlD49lJwVVfmFuA0CTaISUrKe3gBk6sQ6+u2goQCuVHY96Zk5eTUTJSOVJ7WTjU0AJAAiKJCQTW6kHoqkADTq-gYdULhKL7fqDYZlS7Va5TZqzSTSeRfUArNRrPQA-zEaAffbIWg1EKgMSwWimRIpVTHaETAbKIaHDJM7Jo9YGX7lTkYL52OlDNSM5lM57ZdEbAYCgCQQqF3K8KnUnPKcqUvzaplYcRQrAcMuZur1GSyKtIpjUSvh8yR8rVmM6wN5gplHFw22wNiaY1ORUVXJ5wB6AG4nUyDTKQxlEASRET3lQvddUlk1G07KY44tSHzQAADOJUaBwHPBw1Rwn4S2I86QhMTWEzcQIhZfIaqEm0LJx2tFPolvWIBtzRGgAPBwdNmTaDGwUdAA

或者这是实际错误...

12:         ({addFoo, ...props}) => {            ^ Could not decide which case to select. Since case 1 [1] may work but if it doesn't case 2 [2] looks promising too. To fix add a type annotation to destructuring [3] or to return [4].
References:
8:   | (Component: React.ComponentType<{| foo: string |}>) => React.ComponentType<EnhancedProps & {addFoo: true}>                                                              ^ [1]
9:   | (Component: React.ComponentType<$Diff<BaseProps, { foo: string }>>) => React.ComponentType<EnhancedProps & {addFoo: false}>       ^ [2]
12:         ({addFoo, ...props}) => {
             ^ [3]
12:         ({addFoo, ...props}) => {
                                   ^ [4]
23: const Enhanced: React.ComponentType<EnhancedProps> = hoc(BaseComponent);
                                        ^ boolean [1] is incompatible with boolean literal `true` [2] in property `addFoo`.
References:
5: type EnhancedProps = {| addFoo?: boolean |}
                                    ^ [1]
8:   | (Component: React.ComponentType<{| foo: string |}>) => React.ComponentType<EnhancedProps & {addFoo: true}>
                                                                                                           ^ [2]
23: const Enhanced: React.ComponentType<EnhancedProps> = hoc(BaseComponent);
                                        ^ undefined [1] is incompatible with boolean literal `true` [2] in property `addFoo`.
References:
5: type EnhancedProps = {| addFoo?: boolean |}
                                    ^ [1]
8:   | (Component: React.ComponentType<{| foo: string |}>) => React.ComponentType<EnhancedProps & {addFoo: true}>
                                                                                                           ^ [2]
23: const Enhanced: React.ComponentType<EnhancedProps> = hoc(BaseComponent);
                                                         ^ Cannot assign `hoc(...)` to `Enhanced` because `React.ComponentType` [1] is not an object.
References:
9:   | (Component: React.ComponentType<$Diff<BaseProps, { foo: string }>>) => React.ComponentType<EnhancedProps & {addFoo: false}>
                   ^ [1]
23: const Enhanced: React.ComponentType<EnhancedProps> = hoc(BaseComponent);
                                                         ^ all branches are incompatible: Either inexact `React.ComponentType` [1] is incompatible with exact `React.Element` [2]. Or `React.ComponentType` [1] is incompatible with `React.Portal` [3]. Or property `@@iterator` is missing in `React.ComponentType` [1] but exists in `$Iterable` [4].
References:
9:   | (Component: React.ComponentType<$Diff<BaseProps, { foo: string }>>) => React.ComponentType<EnhancedProps & {addFoo: false}>                                                                              ^ [1]
[LIB] ..//static/v0.89.0/flowlib/react.js:18:   | React$Element<any>                                                  ^ [2]
[LIB] ..//static/v0.89.0/flowlib/react.js:19:   | React$Portal                                                  ^ [3]
[LIB] ..//static/v0.89.0/flowlib/react.js:20:   | Iterable<?React$Node>;
                                                  ^ [4]

1 个答案:

答案 0 :(得分:0)

我认为您想念的是:

  

确切对象类型的交叉点可能无法按您预期的方式工作。如果你   需要结合确切的对象类型,使用对象类型传播。

doc

另外,最好临时使用generics,因为包装的组件道具可能对于每个组件都是特定的。

import * as React from 'react'

type EnhancedProps = {| addFoo?: boolean |}
type BaseProps = {| foo?: string |}

const hoc = <T>(Component: React.ComponentType<T>): React.ComponentType<{...EnhancedProps, ...T}> => 
        ({addFoo, ...props}) => {
          if (addFoo) {
              props = {...props, foo: 'Hi'}
          }
          (props: {...T, ...EnhancedProps})
          return <Component {...props}/>;
        }


const BaseComponent = ({foo}: BaseProps) => `Hello`;

const Enhanced: React.ComponentType<{...BaseProps, ...EnhancedProps}> = hoc<BaseProps>(BaseComponent);

<Enhanced />;
<Enhanced addFoo/>;

Try