Flow: Regression in v0.38.0 when checking object properties in conditionals

Created on 1 Feb 2017  路  6Comments  路  Source: facebook/flow

This appears related to #1879, but another bug was added in v0.38.0:

type ExactObj = {|
    a: string
|};

const someObj: ExactObj = {a: 'string'};
const test1 = someObj.COMPLAIN_PLZ; // expected error
if (someObj.COMPLAIN_PLZ) { // bug: should complain

}

// Errors in 0.37.4, not in 0.38.0 or master.
if (someObj.COMPLAIN_PLZ === true) { // bug: should complain. 

}

if (Boolean(someObj.COMPLAIN_PLZ)) { // expected error

}

Try it.

This special-casing of conditionals appears also related to https://github.com/facebook/flow/issues/3309.

I don't see why conditionals should have special rules; someObj.missingProperty should be an error regardless of where it's written, and we should be encouraging hasOwnProperty or in checks.

Most helpful comment

We've relaxed sentinel checks to allow you to check unknown properties. This is consistent with other conditionals

I cannot find a reason why would that be relaxed for Exact types.
It makes something like this fragile:

type BagOfFlags = {|
  a: boolean,
  b: boolean,
  // REMOVED c: boolean
|}

declare var bag: BagOfFlags;

if (bag.c) { // would be nice not to typecheck after c is REMOVED
  // ...
}

IMO, it should not be relaxed even for non exact types, since it leads to dangerous implicit any like in #3309 .
Can this be made configurable in flowconfig?

All 6 comments

This is clearly not a bug or regresseion, it's even mentioned in the changelog:

We've relaxed sentinel checks to allow you to check unknown properties. This is consistent with other conditionals

My apologies, missed that; came up as it appears some refinement being done relates to #3309.

To be honest, I don't understand this change too

We've relaxed sentinel checks to allow you to check unknown properties. This is consistent with other conditionals

I cannot find a reason why would that be relaxed for Exact types.
It makes something like this fragile:

type BagOfFlags = {|
  a: boolean,
  b: boolean,
  // REMOVED c: boolean
|}

declare var bag: BagOfFlags;

if (bag.c) { // would be nice not to typecheck after c is REMOVED
  // ...
}

IMO, it should not be relaxed even for non exact types, since it leads to dangerous implicit any like in #3309 .
Can this be made configurable in flowconfig?

With exact objects you might want to do this:

type T = {| foo: string |} | {| bar: string |};
declare var a: T;
const x: ?string = a.foo;

Is that possible to make this configurable? @vkurchatkin

Was this page helpful?
0 / 5 - 0 ratings