FlowJS: How to use union types and boolean literals

Palisand

Flow questions seem to garner few answers, but here goes:

type Base = {
  foo: string,
  bar: string
}
type Derived1 = Base & {
  conditional: false
}
type Derived2 = Base & {
  conditional: true,
  baz: string
}

type One = {
  foo: string,
  bar: string,
  conditional: boolean
}
type Two = One & {
  baz: string
}

type Return1 = Derived1 | Derived2  // fails

type Return2 = One | Two  // works, but not desired

function test(conditional: boolean): Return1 {
  return {
    foo: "foo",
    bar: "bar",
    conditional,
    ...conditional ? {baz: "baz"} : {}
  }
}

It is preferable for the return value of test to be one of the Derived* types (Return1 rather than Return2), where the conditional property is a boolean literal.

The intention is for flow to understand that if conditional is true, then the object test returns must contain baz and vice versa.

Is this not possible?

adrice727

Flow isn't quite smart enough to figure it out for you. You have to do something like:

function test(conditional: boolean): Return1 {

  const base = {
    foo: "foo",
    bar: "bar",
  }

  if (!conditional) {
    return Object.assign({}, base, { conditional });
  } else {
    const result: Derived2 = Object.assign({}, base, { conditional }, {baz: "baz"});
    return result;
  }
}

More info here: https://flow.org/blog/2016/07/01/New-Unions-Intersections/

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related