In lib/core.js:
static values(object: any): Array<mixed>;
This method doesn't seem to be compatible with a custom type because it is defined as a mixed array.
Simple example:
types:
type Person = {
name: string
}
export type People = Array<Person>;
function:
const getPeople = (): People => {
// fetch data from an api for example
const people = {
john: {
name: "John"
},
frank: {
name: "Frank"
}
}
return Object.values(people);
}
Which results in something like:
return Object.values(people);
^^^^^^^^^^^ call of method `values`
export type People = Array<Person>;
^^^^^ object type. This type is incompatible with. See: app/actions/types.js:75
Does this mean flow users need to rewrite utility functions like .values() to account for custom types?
Object type implies that an instance has particular properties, but it doesn't mean that it doesn't have any other properties. So, mixed is the only safe option
@vkurchatkin well, it does if you annotate it:
type Person = {
name: string,
};
type: People = {
[key: string]: Person,
};
const people: People = {
john: {
name: "John"
},
frank: {
name: "Frank"
}
};
I'd follow this issue: https://github.com/facebook/flow/issues/2174
@vkurchatkin I've seen that touted a couple of times, but the main problem is that the same functionality can be implemented in a 'type-safe' way using Object.keys.
type Person = { name: string };
type People = { [string]: Person };
const people = {
john: { name: 'john'},
frank: { name: 'frank' },
}
const fromValue: Array<Person> = Object.values(people); // fails
const fromKeys: Array<Person> = Object.keys(people).map(key => people[key]); // works
Here is the same code in the 'Try' page.
To my understanding, the fromKeys
is essentially the same as the underlying implementation of fromValues
(at least, that's how polyfill libs did it for a while). And I can't see how using keys
can be any more sure of what 'values' will be present.
Please reopen this issue.
The last example posted by @deecewan demonstrates how Object.values: mixed
is wrong or not consistent.
given my understanding of how flow treats objects, I think this should be good as a libdef:
declare function values<T>(p: { [string]: T }): Array<T>;
declare function values(p: Object): Array<mixed>;
This way, if a known object is passed in (with only a single value type), it returns an array of the known values. If any other object type is passed in, it returns an array of mixed.
this repl shows it in action. Unless I'm missing something, this should work.
Edit: In fact, this same thing should work for Object.entries
.
Hmm, this looks promising. I'd like to examine this more closely. PR @deecewan?
I started one earlier. There were a couple of issues.
I'll finish it up and put it up for comment in the morning.
@deecewan this looks correct
It seems to work in most cases for values
. For some reason, my implementation was no working correctly with entries
. I'll look into it soon.
Why is this still closed?
Object.values
resulting in Array<mixed>
every time, no matter what, is a bug.
Object.entries
resulting in Array<[string, mixed]>
every time, no matter what, is a bug.
I just love it how there's now way to use Object.values
with flow. It really just is unusable.
@nnmrts I just avoid values
and entries
and use Object.keys(...).map(...)
instead
@deecewan Great! You could also just use instanceof
every time!
Or even better, just use the // $FlowFixMe
comment over every second line!
No, wait, even better, just typecheck by hovering over every variable in your IDE, that will do it!
I think other issue already exists
Really, why is this issue closed? "Avoid using Object.values(), use Object.keys() instead" is not a solution. Code should not depend on instruments like Flow, especially when we talk about native methods like Object.values().
Most helpful comment
@vkurchatkin I've seen that touted a couple of times, but the main problem is that the same functionality can be implemented in a 'type-safe' way using Object.keys.
Here is the same code in the 'Try' page.
To my understanding, the
fromKeys
is essentially the same as the underlying implementation offromValues
(at least, that's how polyfill libs did it for a while). And I can't see how usingkeys
can be any more sure of what 'values' will be present.