https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAodBjOA7AzgFzAEEAuYgJ3IEMBPAHgG8qyDyBLbAcwBowAjMgH5WHTgF8AfGAC8YANqowYBmGZgA5FDhx1vARqrqwY7ouWqy6vlXK7+lvkZNmVaq1QBed-dgCuMGGNUAF1ULDxCKDImFnx2Lj0hES4xGSk+bRgAUypsGTA4PgArNLB8GgAHLLgoAuKAOj4ZaVl1ZM51MJwCMAAhMiJKWkY1dsSwdsl8onqoNhh8LPIACigASiA
const A: Array<{a: string, b: ?string}> = [
{ a: 'foo', b: 'a' },
{ a: 'bar', b: 'a' },
{ a: 'baz', b: null }
]
const f: { a: string, b: ?string } => boolean = obj => typeof obj.b === 'string'
const B: Array<{a: string, b: string}> = A.filter(f)
errors:
10: const B: Array<{a: string, b: string}> = A.filter(f) ^ Cannot assign `A.filter(...)` to `B` because null or undefined [1] is incompatible with string [2] in property `b` of array element.
References:
4: const A: Array<{a: string, b: ?string}> = [
^ [1]
10: const B: Array<{a: string, b: string}> = A.filter(f)
^ [2]
Refinement for filter doesn't work. It's known. User reduce or flatMap instead where you need refinement.
filter works when you use the special construct filter(Boolean) to filter out falsy values like null. So the alternative to using something like a // $FlowIssue comment to disable Flow for a line of code is to first use map to map whatever is to be filtered to null and the remove it using the beforementioned construct, at the cost of an additional loop construct. Actually using boolean values does not work though, it has to be null or undefined for the falsy value (for Flow, the Javascript code would of course be okay with it).
Example (1st example with booleans has errors, second one with null does not)
Most helpful comment
Refinement for
filterdoesn't work. It's known. UserreduceorflatMapinstead where you need refinement.https://github.com/facebook/flow/issues/1414