Flow: $Diff with object containing maybe properties behaves unexpectedly

Created on 17 Apr 2018  路  7Comments  路  Source: facebook/flow

If I $Diff an object that contains maybe properties with one that has the same properties but without the maybe, we receive an odd type error:

type SomeProps = {
  id: number,
  name?: string,
};

type SomePropsWithoutName = $Diff<SomeProps, {name: string}>;

const foo: SomePropsWithoutName = {id: 1}
6: type SomePropsWithoutName = $Diff<SomeProps, {name: string}>;
                               ^ Cannot instantiate `$Diff` because undefined [1] is incompatible with string [2].
References:
3:   name?: string,
            ^ [1]
6: type SomePropsWithoutName = $Diff<SomeProps, {name: string}>;

This is useful to do with e.g. React-Redux's connect() functionality, where you might inject props into a component and return one with a new type signature where the properties you provided are no longer required. If one of the properties you provide fills in a maybe type (name? above), the resulting Props are not correct.

Try Flow

destructors

Most helpful comment

This is preventing my team from taking full advantage of Flow when using react-redux. My team is willing to invest some time fixing this, but some details would go a long way.

Here are my questions.

  1. Is there currently a plan to fix this?
  2. Is the required skill and domain knowledge prohibitive to the point that outside contribution to this specific issue would likely be rejected?
  3. Would the preferred solution be a rehash of $Diff, a new utility type, or some other solution?

Let me know, thanks!

All 7 comments

I've managed to work around it with $ObjMap:

type SomeProps = {
  id: number,
  name?: string,
  another: string
};
type MakeMaybeMember = <V>(V) => ?V;
type MergeType = {name: string, another: string};
type SomePropsWithoutName = $Diff<SomeProps, $ObjMap<MergeType, MakeMaybeMember>>;

const foo: SomePropsWithoutName = {id: 1}

Try Flow

I've worked around this by diffing with an object with optional properties:

type SomeProps = {
  id: number,
  name: string,
};

type SomePropsWithoutName = $Diff<SomeProps, {name?: string}>;

const foo: SomePropsWithoutName = {id: 1}

Try Flow

Yeah. Issue is that I don't always control the type that's behind diffed.
It is often inferred from a function and thus is not an optional type.

Is there a reason why $Diff cares about the values of the object type properties at all? To me $Diff should only care about the keys and completely ignore the property values.

I did encounter scenarios where the value type mattered. As a workaround you can use any as a value, which seemed to work for me in all situations.

type WithoutBar = $Diff<Foo, {bar?: any}>;

I did encounter scenarios where the value type mattered.

Like what?

Seems like a $DiffAsYouWouldExpectItToWork type is needed:

type $DiffAsYouWouldExpectItToWork<Props, PropsToRemove> = $Diff<SomeProps, $ObjMap<PropsToRemove, <V>(V) => any>>;

type SomeProps = {
  id: number,
  name?: string,
};

type SomePropsWithoutName = $DiffAsYouWouldExpectItToWork<SomeProps, {name: string}>;

const foo: SomePropsWithoutName = {id: 1}

This is preventing my team from taking full advantage of Flow when using react-redux. My team is willing to invest some time fixing this, but some details would go a long way.

Here are my questions.

  1. Is there currently a plan to fix this?
  2. Is the required skill and domain knowledge prohibitive to the point that outside contribution to this specific issue would likely be rejected?
  3. Would the preferred solution be a rehash of $Diff, a new utility type, or some other solution?

Let me know, thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Beingbook picture Beingbook  路  3Comments

damncabbage picture damncabbage  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments

glenjamin picture glenjamin  路  3Comments

john-gold picture john-gold  路  3Comments