Flow中的假阳性谓词函数类型检查,该函数返回其参数的取反

时间:2019-02-21 22:32:16

标签: javascript flowtype

此代码:

type Predicate = any => boolean;

const xs = [1, 2, 3, 4, 5, 6];
const isEven = (x: number): boolean => x % 2 === 0;
const filter = (pred: Predicate) => (xs: Array<number>) => xs.filter(pred);

filter(isEven)(xs);
Flow认为

很好。但是,此代码:

type Predicate = any => boolean;

const xs = [1, 2, 3, 4, 5, 6];
const filter = (pred: Predicate) => (xs: Array<number>) => xs.filter(pred);

filter(x => -x)(xs);

也被认为很好。这很奇怪,因为函数x => -x永远不会返回布尔值。如果我对谓词中的参数类型更具体,并说它必须是数字,例如

type Predicate = number => boolean;

const xs = [1, 2, 3, 4, 5, 6];
const filter = (pred: Predicate) => (xs: Array<number>) => xs.filter(pred);

filter(x => -x)(xs);

然后让Flow显示一些相关的错误,就像应该的那样:

6: filter(x => -x)(xs);
                ^ Cannot call `filter` with function bound to `pred` because number [1] is incompatible with boolean [2] in the return value.
References:
1: type Predicate = number => boolean;
                    ^ [1]
1: type Predicate = number => boolean;
                              ^ [2]

同时,如果我尝试使该函数返回更突出的类型,则Flow会发现问题。 Flow将这些调用全部正确地视为包含类型错误:

filter(x => String(x))(xs); // <- string is incompatible with boolean, okay
filter(x => Number(x))(xs); // <- number is incompatible with boolean, also okay
filter(x => +x)(xs); // <- +x will always evaluate into a number or NaN, never a boolean
filter(x => x & x)(xs); // <- number is incompatible with boolean

是否有一种方法可以针对特定情况x => -x进行类型检查,并让Flow显示错误?还是Flow在这种情况下是否正确进行类型检查,只是我遗漏了一些东西?

1 个答案:

答案 0 :(得分:1)

使用以下通用类型可以在此处提供帮助

type Result<T> = Array<T> => Array<T>;

const xs = [1, 2, 3, 4, 5, 6];
const filter = <T>(pred: (T) => boolean): Result<T> => xs => xs.filter(pred);

filter(x => -x)(xs);

尝试以下操作:https://flow.org/try/#0C4TwDgpgBAShDOBXANsAPAFQHxQLxQEEAnIgQxEx1x2LIuwG4AoJgYwHsA7eYKAD3h4oAbQCMAGigAmSQGZJAFkkBWSQDYAusw7deAMwCWqCESGUAFGCIQAJgC4o5jAEo8OAEbt2yCKU7OHOCRUSjd+QWpwgDpDYyJLaxtnZiZY4BNzPjCAWj5nTPhkoA