Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$Diff is not compatible with object intersections #3246

Closed
aldendaniels opened this issue Jan 23, 2017 · 5 comments
Closed

$Diff is not compatible with object intersections #3246

aldendaniels opened this issue Jan 23, 2017 · 5 comments

Comments

@aldendaniels
Copy link

aldendaniels commented Jan 23, 2017

type AB = {a: number, b: number};
type A = {a: number};
type B = {b: number};

const x: $Diff<AB, A & B> = {};

Gives:

6: const x: $Diff<AB, A & B> = {};
                  ^ property `b`. Property not found in
6: const x: $Diff<AB, A & B> = {};
                               ^ object literal

The right half of the union is ignored. This makes certain types of HoCs impossible to type.

@rsolomon
Copy link

This issue is killing me as well. Is there a working alternate approach that anyone has found?

@nmn nmn changed the title $Diff is not compatible with unions $Diff is not compatible with object intersections Mar 21, 2017
@nmn
Copy link
Contributor

nmn commented Mar 21, 2017

This works:

type AB = {a: number, b: number};
type A = {a: number};
type B = {b: number};

const x: $Diff<$Diff<AB, A>, B> = {};

I think this should work too:

type AB = {a: number, b: number};
type A = {a: number};
type B = {b: number};

const x: $Diff<AB, {...A, ...B}> = {};

But right now object type spread doesn't work in any generic location.

@aldendaniels
Copy link
Author

@rsolomo My workaround has been to manually create the wrapping components for HoCs.

The traditional HoC is created using:

function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {
    render() {
      return <WrappedComponent ... />;
    }
  };
}

class MyComponentImpl extends React.Component {
  ...
}

MyComponent = withSubscription(MyComponentImpl);

The problem is that MyComponent now takes different props than MyComponentImpl and it's not easy for flow (or humans) to do the math on what props to provide MyComponent.

Instead, I prefer to do this:

  class MyComponentImpl extends React.Component {
    ...
  }

  class WithSubscription extends React.Component {
    props: {
      render: (InjectedProps) => React$Element<*>,
    }

    render() {
      return this.props.render(injectedProps);
    }
  }

  class MyComponent extends React.Component {
   renderWithSubscription(injectedProps) {
     return <MyComponnent {...injectedProps} />;
   }

    render() {
      return <WithSubscription />
    }
  }

It's the same thing really, but at the cost of a little verbosity, it reduces all the ambiguity about props and makes using flow a synch.

@kevinbarabash
Copy link

I substituted $Rest for $Diff in my HOC definition and it fixed the issue when the HOC wraps a component whose props are a disjoint union.

@SamChou19815
Copy link
Contributor

This now works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants