简体   繁体   中英

Flow types for optional parameter in higher order React component

I'm trying to create a higher order component using Flow types, but am having trouble with the returned component type.

Minimal example:

/* @flow */

import React from 'react';

type Props = {
  name: string,
  what: number
}

const TestComponent = (props: Props) => null

function withDefaultClassname<Config: {}>(
  Component: React$AbstractComponent<Config, *>
): React$AbstractComponent<{...$Exact<Config>, name: string}, *> {
  return (props) => <Component {...props} className={props.className || 'default'} />;
}
const Wrapped2 = withDefaultClassname(TestComponent)

// $ExpectError - should complain about undefined props
const a = <Wrapped2 />

In the example above, the higher order component sets the className prop if it doesn't exist, otherwise uses the provided prop. Therefore, I've tried to set the return type of the higher order component to set className as an optional prop. Nevertheless, this seems to cause issues whereby otherwise required props are no longer enforced by Flow. Is there a better way to do this?

The Flow documentation talks about injecting props , but that involves using the $Diff utility type. I'd like to indicate that the return type here does include className as an optional prop, making the $Diff utility type unhelpful in this case.

Config & {className?: string} seems to works correctly :

function withDefaultClassname<Config: {}>(
      Component: React$AbstractComponent<Config, *>
    ): React$AbstractComponent<Config & {className?: string}, *> {
      return (props) => <Component className={props.className || 'default'} {...props} />;
    }

Spread operators is better to use for merging exact types .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM