Flow: Union type-testing weirdness on https://flowtype.org/try

Created on 27 Jul 2016  路  7Comments  路  Source: facebook/flow

Is Try running flow 0.29? The string at the bottom of https://flowtype.org/assets/flow.js suggests so, but I ran into an odd difference between it and a fresh flow project running locally.

https://flowtype.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgDCMAljgMp4DGGJcAdmALxgDeqYYVpOAzgFxgA2gF1UAX0y4CABRgBDLKV4ZKNOoxbtOOBUpIqBwsZNRQArvXUMwUOHAAUvarQaDiZNa8YAfMHMVlVRcNAEo2DjASKDAnEIYAOm4yXnDtTi4GXjgYPAT4AHM463oknl58vHoCjAALUMjxMDwYZyiY4u8E3UCDDFSIjM4qLJy8ws6Nbr0gitzquobOSUk7R1ZkvkEhAEYAGgAmEXEGtYdWHv1DbYBmPYAWY4agA

/* @flow */

type ClipSection = {
  clips: []
}
type PlaylistSection = {
  playlists: []
}

function foo(section: ClipSection | PlaylistSection) {
  if (section.clips) {
    console.log(section.clips.length)
  } else if (section.playlists) {
     console.log(section.playlists.length)
  }
}
foo({clips: [1,2]})
foo({playlists: [3,4]})

gives this error:

11:   if (section.clips) {
                  ^ property `clips`. Property not found in
11:   if (section.clips) {
          ^ object type

The same code running locally appears to have no issues.

Most helpful comment

@jedwards1211 Hi Andy - just to confirm, Gabe's description has the problem and the intended solution exactly right. (The idea is to follow up later with some syntactic sugar, but the behavior shouldn't change.) cc @gabelevi thanks Gabe!

All 7 comments

There's two questions here.

  1. What version of flow is flowtype.org/try running? The answer is that it is currently running master. That is, whenever we commit to GitHub, Travis rebuilds our website and includes the most recent version of flow.js. We should probably mention this on flowtype.org/try/ and maybe even give the option to run against different versions of Flow
  2. The error you're seeing is something that's in master. I reverted that change on the 0.30.0 release branch, since it's not ready for consumption yet, though. The commit that added this behavior is https://github.com/facebook/flow/commit/32f09ffe5d7b23280b638578b13982cc5c9696ed, but we're waiting on a few other improvements (like https://github.com/facebook/flow/commit/f3cacf173baca3cc1674c2c8fac0b33d247c3cbd) before we roll it out. @bhosmer is the mastermind of this project

Why does your code error on master? Well, Flow's object types are not _exact_ at the moment.

type PlaylistSection = {
  playlists: []
}
({ playlists: [] }: PlaylistSection) // This is ok, as expected
({ playlists: [], clips: 123 }: PlaylistSection) // This is also ok

And the reason this is a big deal is that when we do

function foo(section: ClipSection | PlaylistSection) {
  if (section.clips) {
    console.log(section.clips.length)
  } 
  ...

inside the if block we don't actually know for sure that section is a ClipSection. All we know is that there is a truthy clips property, but it could be a PlaylistSection with a clips property.

Exact types will help, because you'll be able to tell Flow something like

type PlaylistSection = $Exact<{
  playlists: []
}>

and now we know that a valid PlaylistSection only has a playlists property and will never have a clips property.

Ohhh. Makes sense, thanks for the update.

@gabelevi so in essence you're saying that in the future with the following code:

type ClipSection = $Exact<{
  clips: [],
  name: string,
}>
type PlaylistSection = $Exact<{
  playlists: []
}>

function foo(section: ClipSection | PlaylistSection) {
  if (section.clips) {
    // flow will know section is a ClipSection
    console.log(section.name) // and this will typecheck ok
  }
}

@jedwards1211 - I think so, but I'll poke @bhosmer to see if I'm misrepresenting things. Also we haven't completely built the future yet, and sometimes we hone our intuition as we go.

Yeah. Looking forward to this or whatever you guys decide to implement in its place!

@jedwards1211 Hi Andy - just to confirm, Gabe's description has the problem and the intended solution exactly right. (The idea is to follow up later with some syntactic sugar, but the behavior shouldn't change.) cc @gabelevi thanks Gabe!

Closing, seems resolved above.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Beingbook picture Beingbook  路  3Comments

ghost picture ghost  路  3Comments

mjj2000 picture mjj2000  路  3Comments

john-gold picture john-gold  路  3Comments

bennoleslie picture bennoleslie  路  3Comments