Flow: Property assignment on object with null prototype fails

Created on 17 Sep 2015  路  8Comments  路  Source: facebook/flow

Flow currently does not typecheks following code snippet:

/* @flow */
export var html = Object.create(null);

["a","abbr","address"].forEach(tagName => {
  html[tagName] = (properties, children) =>
    ({tagName, properties, children})
});

producing following error:

/Users/gozala/Projects/reflex/src/core.js:4:1,7:2: call of method forEach
Error:
/Users/gozala/Projects/reflex/src/core.js:4:2,4: property `a`
Property not found in possibly null value
/Users/gozala/Projects/reflex/src/core.js:2:33,36: null

/Users/gozala/Projects/reflex/src/core.js:4:1,7:2: call of method forEach
Error:
/Users/gozala/Projects/reflex/src/core.js:4:6,11: property `abbr`
Property not found in possibly null value
/Users/gozala/Projects/reflex/src/core.js:2:33,36: null

/Users/gozala/Projects/reflex/src/core.js:4:1,7:2: call of method forEach
Error:
/Users/gozala/Projects/reflex/src/core.js:4:13,21: property `address`
Property not found in possibly null value
/Users/gozala/Projects/reflex/src/core.js:2:33,36: null
bug

Most helpful comment

This form also errors:

var foo = Object.create(null, {
  bar: 1
});

```
1: var foo = Object.create(null, {
^ .bar of Object.create. Property not found in
2: bar: 1
^ Number


You can work around this like so:
```js
var foo = Object.create(null, ({
  bar: 1
} : any));

You can work around the example @samwgoldman pasted like so:

var foo = (Object.create(null) : Object);
foo.bar = true;

All 8 comments

Simpler repro:

/* @flow */
let o = Object.create(null);
o.p = null;
test.js:4
  4: o.p = null;
       ^ property `p`. Property not found in possibly null value
  3: let o = Object.create(null);
                           ^^^^ null

This is a very old issue. There is no workaround ? There is no fix?

This form also errors:

var foo = Object.create(null, {
  bar: 1
});

```
1: var foo = Object.create(null, {
^ .bar of Object.create. Property not found in
2: bar: 1
^ Number


You can work around this like so:
```js
var foo = Object.create(null, ({
  bar: 1
} : any));

You can work around the example @samwgoldman pasted like so:

var foo = (Object.create(null) : Object);
foo.bar = true;

You could always just do this :rofl:

const known: {[Coords]: number} = /* :: {} || */ Object.create(null)

(it actually works)

@qm3ster, can you explain why this works? Is it an OCaml thing? :see_no_evil:

@clintwood this dark magic is using flow's Comment Syntax.
But, unlike normal use to write types in a file that can be interpreted without preprocessing, here it actually pretends that your javascript is different, and the compiler is none the wiser.
It's definitely a dirty hack.

But the point is, this is what javascript sees:

const known = Object.create(null)

and this is what flow sees:

const known: {[Coords]: number} = {} || Object.create(null)

which since {} is always truthy, is equivalent to

 const known: {[Coords]: number} = {}

Also, my news feed today:
image


Also, there's no flow highlighter, only ts, and that's racist.

It is also possible to do following:

const known: {[Coords]: number} = (Object.create(null):Object)

I'm not entirely sure why flow allows to cast it to Object.

1) That's not as funny
2) That will show as decreased coverage

Was this page helpful?
0 / 5 - 0 ratings