Skip to content

Union type passing depends on order of type definition #1663

@willclarktech

Description

@willclarktech

I'm using flow-bin 0.23.0 and getting an order effect I don't understand with a union type:

// @flow

type OptionAnswer = {
    kind           : 'OptionAnswer',
    currentAnswer? : {},
}

type TextAnswer = {
    kind           : 'TextAnswer',
    currentAnswer? : string,
}

type Answer
    = TextAnswer
    | OptionAnswer

////////////////////////////////////////////

// fine
const exampleOptionAnswer: OptionAnswer = {
    kind: 'OptionAnswer',
}

// fine
const exampleTextAnswer: TextAnswer = {
    kind: 'TextAnswer',
}

const exampleAnswer1: Answer = {
    kind: 'OptionAnswer',
}

const exampleAnswer2: Answer = {
    kind: 'TextAnswer',
}

This gives the following error:

29: const exampleAnswer1: Answer = {
                                    ^ object literal. This type is incompatible with
 29: const exampleAnswer1: Answer = {
                           ^^^^^^ union: TextAnswer | OptionAnswer
  Member 1:
   14:     = TextAnswer
             ^^^^^^^^^^ TextAnswer
  Error:
   30:     kind: 'OptionAnswer',
                 ^^^^^^^^^^^^^^ string. Expected string literal `TextAnswer`, got `OptionAnswer` instead
    9:     kind           : 'TextAnswer',
                            ^^^^^^^^^^^^ string literal `TextAnswer`
  Member 2:
   15:     | OptionAnswer
             ^^^^^^^^^^^^ OptionAnswer
  Error:
   10:     currentAnswer? : string,
                            ^^^^^^ string. This type is incompatible with
    5:     currentAnswer? : {},
                            ^^ object type

If I switch the union type definition to type Answer = OptionAnswer | TextAnswer I get this instead:

33: const exampleAnswer2: Answer = {
                                    ^ object literal. This type is incompatible with
 33: const exampleAnswer2: Answer = {
                           ^^^^^^ union: OptionAnswer | TextAnswer
  Member 1:
   14:     = OptionAnswer
             ^^^^^^^^^^^^ OptionAnswer
  Error:
   34:     kind: 'TextAnswer',
                 ^^^^^^^^^^^^ string. Expected string literal `OptionAnswer`, got `TextAnswer` instead
    4:     kind           : 'OptionAnswer',
                            ^^^^^^^^^^^^^^ string literal `OptionAnswer`
  Member 2:
   15:     | TextAnswer
             ^^^^^^^^^^ TextAnswer
  Error:
    5:     currentAnswer? : {},
                            ^^ object type. This type is incompatible with
   10:     currentAnswer? : string,
                            ^^^^^^ string

I'm pretty new to flow so maybe I'm doing something stupid, but it looks like the literal from the first disjunct is somehow infecting the object that is compared to the second disjunct?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions