Open vicapow opened 7 years ago
It will be easier to help you if you include the error text.
oh, sure
7: a[key] = a[key];
^ number. This type is incompatible with
3: type TypeA = {foo: number, bar: string};
^ string
7: a[key] = a[key];
^ string. This type is incompatible with
3: type TypeA = {foo: number, bar: string};
^ number
I see. I think you understand the issue. Flow doesn't keep track of the fact that key
is the same in both places. That's a more complex analysis and I don't know what it would take to implement it. I think there are lots of opportunities for Flow to do a more precise analysis so I'm not sure when or if we will address this case.
In cases like this, is the ideal workaround to use something like // $FlowFixMe
or maybe an additional type annotation we can add?
@vicapow ideally, you shouldn't write a[key] = a[key]
😄
@vkurchatkin Sorry! I realize it's a silly example but from looking at the other issues, it seemed like folks were looking for simplified reproduction steps. I may have taken that too far :P For more context and to help motivate the issue, I was trying to implement a way to "reset" fields in a form without mutating the original form.
/* @flow */
type Input<T> = {input: T, error: string};
type Form = {foo: Input<number>, bar: Input<string>};
let form = {foo: {input: 0, error: 'a'}, bar: {input: '1', error: 'b'}};
function resetInfo(a: Form): Form {
Object.keys(a).forEach((key: $Keys<Form>)=> {
a[key] = {...a[key], info: ''};
});
return {...a};
}
form = resetInfo(form);
Should see a similar error:
9: a[key] = {...a[key], info: ''};
^ object literal. This type is incompatible with
4: type Form = {foo: Input<number>, bar: Input<string>};
^ object type
9: a[key] = {...a[key], info: ''};
^ object literal. This type is incompatible with
4: type Form = {foo: Input<number>, bar: Input<string>};
^ object type
Here's a similar example:
const obj = {
foo() {},
bar: true
}
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'function') {
obj[key] = obj[key].bind(obj);
}
});
8: obj[key] = obj[key].bind(obj);
^ Cannot assign `obj[key].bind(...)` to `obj[key]` because function [1] is incompatible with boolean [2].
References:
2: foo() {},
^ [1]
3: bar: true ^ [2]
Of course, I can bind obj.foo
directly, but that defeats the purpose here: to loop over arbitrary/unknown properties and only bind the functions.
Apologies if I'm not using the correct terminology. As best I can tell, this seems to be an issue with Flow not maintaining that the type of
key
is the same type in both cases of the read and write of the property.