Flow version: 0.98.0+
const compareGeneric = <T: number>(a: T, b: T): boolean =>
a < b;
// no errors
const compareGeneric = <T: number>(a: T, b: T): boolean =>
a < b;
//^ Cannot compare `T` [1] to `T` [2].
I suspect this is linked to the change in 0.98.0 referenced here, as it's the only thing I could find that sounded sort of related:
Fix an unsoundness with addition or logical operators when combined with generics (#6671, #7070).
Those issues point at this change: https://github.com/facebook/flow/commit/db8a41e4e2fbfca0fffddebb69917b1835789872
So the question I'm left with is, how _should_ I type this comparison function, if not in the way I've typed it? This really _looks_ like it should be fine. Math operators and === all work as expected in the same position.
Not an ideal workaround:
const compareGeneric = <T: number | Date>(a: T, b: T): boolean => a - b > 0;
2 ways I can think of:
const compareGeneric = <T: number | Date>(a: T, b: T): boolean =>
+a < +b;
const compareGeneric2 = <T: number | Date>(a: T, b: T): boolean =>
Number(a) < Number(b);
Thanks, I hate it.
Using Number looks like the clearest option to me.
Is there some underlying reason I should understand that explains why this behavior is correct? Or is this actually a bug?
Seems buggish since it's really easy to defeat, e.g. this doesn't error:
const compareGeneric = <T: number>(a: T, b: T): boolean =>
Boolean(a) && a < b; // Works
Or even nonsensical things:
const compareGeneric = <T: number>(a: T, b: T): boolean =>
isNaN(a) && a < b; // Works
But it also seems like generics aren't really needed here:
const compare = (a: number | Date, b: number | Date): boolean =>
a < b;
thanks @mroch