This comes up quite a bit with our react components whenever we do a refactor. Many of our components take optional types but when we rename those optional types we do not get breaking changes upstream to notify us all the places we need to rename the variable.
If instead there was an option in the .flowconfig to default to $Exact type and create a new utility type $Inexact the reverse of the current scenario would be possible
You can do that yourself?
Just write your types as exact types (with the bars):
type Props = {|
required: string,
optional?: string,
|}
Yea but doing this for every type defined everywhere is a serious pain. Also there is no way to enforce that new developers writing new code align with this standard other than code reviews and pipes are easy to miss.
this could solve Object.values problem
@rickyp-uber https://github.com/gajus/eslint-plugin-flowtype#require-exact-type
require-exact-type
This rule enforces exact object types.
@sibelius that issue still wouldn't be resolved because inexact object would still exist, they just wouldn't be the default.
@lll000111 I have a hard time believing that said eslint plugin covers things like object type spread or any of the utility types that output inexact object types.
@sibelius Exact types definitely help with the Object.values issue. It's one of the main reasons we went that direction
@lll000111 Ooooooh good find! Though not as nice as having it as a single setting somewhere (which i'm leaving this open for) this does seem like a valid alternative. I'll try it next week (earliest in my current schedule) and let you know how it goes.
I can't remember where I have seen this, but the code you are looking is:
type Inexact<T: Object> = {...T};
Still not the same but interesting to know
This is in progress. See 1ac913040f38309480934ccb6717a3ffc65094a8. It looks like the eventual syntax will be {foo: number}
for an exact type and {foo: number, ...}
for an inexact type (literal ellipsis).
It looks like exact is going to become the default behavior eventually. Flow published a blog article about this recently.
If you're not using Babel 7 yet, you have to upgrade to support the ...
syntax in babel-eslint
. Not 100% on that but don't quote me. The codemods/linters have not been released for upgrading either. So, I too, would like to see the $Inexact<>
utility type.
Anyway, I think this is how it all is supposed to work.
Is there not a better solution that is more scoped to the particular problem? This solves the specific problem of optional prop renaming but also makes code more brittle and difficult to change overall. It's like using a sledgehammer to mount a painting. In particular, it makes programming to interfaces (i.e. duck-typing) harder.
With exact object types by default, this would not work by default:
type Item = any;
type Fetcher = {
fetch(key: string): Promise<Item>
};
function fetchItems(fetcher: Fetcher, ...keys: string[]): Promise<Item[]> {
return Promise.all(keys.map(k => fetcher.fetch(k))
}
const myApi = {
fetch(key: string): Promise<Item> {
// ...
},
somethingElse(...args) {
// ...
}
}
// Error if exact object types are enabled by default.
fetchItems(myApi);
@jncornett: Flow supports interfaces. Using them solves the problem in
your example (Flow Try link):
// @flow
type Item = any;
interface Fetcher {
fetch(key: string): Promise<Item>;
}
function fetchItems(fetcher: Fetcher, ...keys: string[]): Promise<Item[]> {
return Promise.all(keys.map(k => fetcher.fetch(k)));
}
const myApi = {
fetch(key: string): Promise<Item> {
throw new Error("Not yet implemented");
},
somethingElse(...args) {
// ...
}
};
// No error (good)
fetchItems(myApi);
@wchargin isn't this is old syntax for interfaces and new one is
type A = interface {...}
?
@goodmind: Inline interface types were indeed added in Flow v0.73.0, but
there’s certainly nothing wrong with the “old” syntax, and I don’t see
any reason to prefer the “new” one.
I think this is resolved?
Most helpful comment
I can't remember where I have seen this, but the code you are looking is: