-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disjoint union type filtering is not respected when filtering arrays #6516
Comments
This is a known limitation. The problem is that the type of declare class Array<T> {
filter(predicate: (T) => boolean): Array<T>;
} so when you call
That the type of the result array should be refined according to your I don’t have a good workaround other than a cast through const res: Object1[] = $Downcast(testArray.filter((x) => x.type === 'one')); to express that you are guaranteeing to Flow that the type of the result (Also related: #6397.) |
I do like the way that looks, thanks for the suggestion. Unfortunately, though $Downcast does sound enticing, I would rather flow support it automatically. For instance, as shown in the docs, flow can automatically infer which type you are using in many cases (such as if statements). What part of the engine stops it from being able to also check the predicate I pass to |
flows refinement system can't infer the types of anything that is not in the current scope. For everything outside of the current scope flow has to rely on the exposed signature. The fact that The problem here is that the there is no way expressing that the predicate used in This problem exists in every language that has map/filter functionality. There is a trick to get around this though. Since all we need is to have a way to grab onto the expected result type we have to find a function that takes a function that includes it. What about interface Array<A> {
...
map(f: (a:A) => B)): Array<B>;
...
} The return type of the mapping function As you can see inside the mapping function type refinements work out of the box even without explicit type annotations on the return type. Unfortunately the This trick also works for the java |
Thanks for the informative answer! |
It depends on what you mean by this. It’s not currently possible to even write down the type that you’d declare class Array<T> {
function filter<U>(p: PredicateReturningTrueOnlyFor<U>): Array<U>;
} So, if you mean, “keeping the current grammar of types and values, is it But maybe you’re willing to permit expanding the grammar to give us more declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
declare var arr: Array<mixed>;
const barr = my_filter(arr, is_string);
(barr: Array<string>);
function is_string(x): %checks {
return typeof x === "string";
} I don’t know what the status of this code is, but it doesn’t look like
So would I! Sorry that this may not be a satisfying answer; it’s just |
That's really helpful! I definitely appreciate the in-depth explanations you guys have given about how Flow works. That other thread was also helping in understanding the limitations and possible improvements Flow could see. |
Summary: This diff splits `RawThreadInfo` into `RawThinThreadInfo` (basically the old type) and `RawThickThreadInfo`, which will be used for E2E-encrypted DMs. The latter type includes `ThreadSubscription` for each member. I tried to break this diff down but it was tough due to Flow issues. This diff doesn't update `ThreadInfo`. That type is used generally in frontend code, and I'm not sure we'll need the new `ThreadSubscription`. This diff also doesn't do anything to make sure we handle `RawThickThreadInfo` correctly when we encounter it. That will be handled in later tasks. It's okay to commit this type change now as we aren't actually introducing `RawThickThreadInfo` to any stores. On the Flow side here, I had to add a `thick: true` attribute. I initially tried to differentiate the two types through the `type` field, which should let us represent `RawThreadInfo` was a union of two disjoint types (`RawThinThreadInfo` and `RawThickThreadInfo`). But I wasn't able to get Flow to narrow the types when I checked the `type` field. Here's what I tried: - Enumerating all of the possible values of `type` at every location, for both the thick and thin conditions. This worked but was way too verbose - Considered using [type guards](https://flow.org/en/docs/types/type-guards/), but our setup [doesn't support](https://flow.org/en/docs/types/type-guards/#toc-adoption) them yet. More details in [this blog](https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf) - Considered using an older version of type guards: assert functions that use `%checks`. However this wasn't able to narrow a `threadInfo` by checking `threadInfo.type` for some reason - Considered using assert functions that just have `invariant`s and `any`s instead of `%checks`. This resulted in four functions: `assertThinRawThreadInfo`, `assertThickRawThreadInfo`, `assertLegacyThinRawThreadInfo`, `assertLegacyThickRawThreadInfo`. A pair of these would be combined with a `threadTypeIsThick` check. Ultimately decided it was too verbose - Referenced [this GitHub issue](facebook/flow#6516 (comment)) where something similar is discussed Depends on D12494 Test Plan: Flow Reviewers: kamil, marcin Subscribers:
Summary: This diff splits `RawThreadInfo` into `RawThinThreadInfo` (basically the old type) and `RawThickThreadInfo`, which will be used for E2E-encrypted DMs. The latter type includes `ThreadSubscription` for each member. I tried to break this diff down but it was tough due to Flow issues. This diff doesn't update `ThreadInfo`. That type is used generally in frontend code, and I'm not sure we'll need the new `ThreadSubscription`. This diff also doesn't do anything to make sure we handle `RawThickThreadInfo` correctly when we encounter it. That will be handled in later tasks. It's okay to commit this type change now as we aren't actually introducing `RawThickThreadInfo` to any stores. On the Flow side here, I had to add a `thick: true` attribute. I initially tried to differentiate the two types through the `type` field, which should let us represent `RawThreadInfo` was a union of two disjoint types (`RawThinThreadInfo` and `RawThickThreadInfo`). But I wasn't able to get Flow to narrow the types when I checked the `type` field. Here's what I tried: - Enumerating all of the possible values of `type` at every location, for both the thick and thin conditions. This worked but was way too verbose - Considered using [type guards](https://flow.org/en/docs/types/type-guards/), but our setup [doesn't support](https://flow.org/en/docs/types/type-guards/#toc-adoption) them yet. More details in [this blog](https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf) - Considered using an older version of type guards: assert functions that use `%checks`. However this wasn't able to narrow a `threadInfo` by checking `threadInfo.type` for some reason - Considered using assert functions that just have `invariant`s and `any`s instead of `%checks`. This resulted in four functions: `assertThinRawThreadInfo`, `assertThickRawThreadInfo`, `assertLegacyThinRawThreadInfo`, `assertLegacyThickRawThreadInfo`. A pair of these would be combined with a `threadTypeIsThick` check. Ultimately decided it was too verbose - Referenced [this GitHub issue](facebook/flow#6516 (comment)) where something similar is discussed Depends on D12494 Test Plan: Flow Reviewers: kamil, marcin Subscribers: tomek Differential Revision: https://phab.comm.dev/D12495
Summary: This diff splits `RawThreadInfo` into `RawThinThreadInfo` (basically the old type) and `RawThickThreadInfo`, which will be used for E2E-encrypted DMs. The latter type includes `ThreadSubscription` for each member. I tried to break this diff down but it was tough due to Flow issues. This diff doesn't update `ThreadInfo`. That type is used generally in frontend code, and I'm not sure we'll need the new `ThreadSubscription`. This diff also doesn't do anything to make sure we handle `RawThickThreadInfo` correctly when we encounter it. That will be handled in later tasks. It's okay to commit this type change now as we aren't actually introducing `RawThickThreadInfo` to any stores. On the Flow side here, I had to add a `thick: true` attribute. I initially tried to differentiate the two types through the `type` field, which should let us represent `RawThreadInfo` was a union of two disjoint types (`RawThinThreadInfo` and `RawThickThreadInfo`). But I wasn't able to get Flow to narrow the types when I checked the `type` field. Here's what I tried: - Enumerating all of the possible values of `type` at every location, for both the thick and thin conditions. This worked but was way too verbose - Considered using [type guards](https://flow.org/en/docs/types/type-guards/), but our setup [doesn't support](https://flow.org/en/docs/types/type-guards/#toc-adoption) them yet. More details in [this blog](https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf) - Considered using an older version of type guards: assert functions that use `%checks`. However this wasn't able to narrow a `threadInfo` by checking `threadInfo.type` for some reason - Considered using assert functions that just have `invariant`s and `any`s instead of `%checks`. This resulted in four functions: `assertThinRawThreadInfo`, `assertThickRawThreadInfo`, `assertLegacyThinRawThreadInfo`, `assertLegacyThickRawThreadInfo`. A pair of these would be combined with a `threadTypeIsThick` check. Ultimately decided it was too verbose - Referenced [this GitHub issue](facebook/flow#6516 (comment)) where something similar is discussed Depends on D12494 Test Plan: Flow Reviewers: kamil, marcin Subscribers: tomek Differential Revision: https://phab.comm.dev/D12495
Summary: This diff splits `RawThreadInfo` into `RawThinThreadInfo` (basically the old type) and `RawThickThreadInfo`, which will be used for E2E-encrypted DMs. The latter type includes `ThreadSubscription` for each member. I tried to break this diff down but it was tough due to Flow issues. This diff doesn't update `ThreadInfo`. That type is used generally in frontend code, and I'm not sure we'll need the new `ThreadSubscription`. This diff also doesn't do anything to make sure we handle `RawThickThreadInfo` correctly when we encounter it. That will be handled in later tasks. It's okay to commit this type change now as we aren't actually introducing `RawThickThreadInfo` to any stores. On the Flow side here, I had to add a `thick: true` attribute. I initially tried to differentiate the two types through the `type` field, which should let us represent `RawThreadInfo` was a union of two disjoint types (`RawThinThreadInfo` and `RawThickThreadInfo`). But I wasn't able to get Flow to narrow the types when I checked the `type` field. Here's what I tried: - Enumerating all of the possible values of `type` at every location, for both the thick and thin conditions. This worked but was way too verbose - Considered using [type guards](https://flow.org/en/docs/types/type-guards/), but our setup [doesn't support](https://flow.org/en/docs/types/type-guards/#toc-adoption) them yet. More details in [this blog](https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf) - Considered using an older version of type guards: assert functions that use `%checks`. However this wasn't able to narrow a `threadInfo` by checking `threadInfo.type` for some reason - Considered using assert functions that just have `invariant`s and `any`s instead of `%checks`. This resulted in four functions: `assertThinRawThreadInfo`, `assertThickRawThreadInfo`, `assertLegacyThinRawThreadInfo`, `assertLegacyThickRawThreadInfo`. A pair of these would be combined with a `threadTypeIsThick` check. Ultimately decided it was too verbose - Referenced [this GitHub issue](facebook/flow#6516 (comment)) where something similar is discussed Depends on D12494 Test Plan: Flow Reviewers: kamil, marcin Subscribers: tomek Differential Revision: https://phab.comm.dev/D12495
Summary: This diff splits `RawThreadInfo` into `RawThinThreadInfo` (basically the old type) and `RawThickThreadInfo`, which will be used for E2E-encrypted DMs. The latter type includes `ThreadSubscription` for each member. I tried to break this diff down but it was tough due to Flow issues. This diff doesn't update `ThreadInfo`. That type is used generally in frontend code, and I'm not sure we'll need the new `ThreadSubscription`. This diff also doesn't do anything to make sure we handle `RawThickThreadInfo` correctly when we encounter it. That will be handled in later tasks. It's okay to commit this type change now as we aren't actually introducing `RawThickThreadInfo` to any stores. On the Flow side here, I had to add a `thick: true` attribute. I initially tried to differentiate the two types through the `type` field, which should let us represent `RawThreadInfo` was a union of two disjoint types (`RawThinThreadInfo` and `RawThickThreadInfo`). But I wasn't able to get Flow to narrow the types when I checked the `type` field. Here's what I tried: - Enumerating all of the possible values of `type` at every location, for both the thick and thin conditions. This worked but was way too verbose - Considered using [type guards](https://flow.org/en/docs/types/type-guards/), but our setup [doesn't support](https://flow.org/en/docs/types/type-guards/#toc-adoption) them yet. More details in [this blog](https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf) - Considered using an older version of type guards: assert functions that use `%checks`. However this wasn't able to narrow a `threadInfo` by checking `threadInfo.type` for some reason - Considered using assert functions that just have `invariant`s and `any`s instead of `%checks`. This resulted in four functions: `assertThinRawThreadInfo`, `assertThickRawThreadInfo`, `assertLegacyThinRawThreadInfo`, `assertLegacyThickRawThreadInfo`. A pair of these would be combined with a `threadTypeIsThick` check. Ultimately decided it was too verbose - Referenced [this GitHub issue](facebook/flow#6516 (comment)) where something similar is discussed Depends on D12494 Test Plan: Flow Reviewers: kamil, marcin Reviewed By: marcin Subscribers: tomek Differential Revision: https://phab.comm.dev/D12495
Reproduced here.
We basically have an array of a disjoint union type. So we have multiple elements in the array, and we differentiate between them based on a
type
property. I use the array methodfilter
to essentially only get an array of objects of one type. However, flow does not infer that the results will only be of the one type. How do I work around this?The text was updated successfully, but these errors were encountered: