Reputation: 1923
I am trying to make a typed wrapper around lodash's isEqual
function. I want it to work only for two arguments of the same type. I have following code:
export function isEqual<T>(a: T, b: T): boolean {
return _.isEqual(a, b);
}
const c: boolean = isEqual('one', 2); // shouldn't it be a type error here?
console.log(c)
But it doesn't work, because it's possible to pass two arguments of different types to it and Flow is fine with that. What is a right way to implement such a function?
I am using Flow version 0.58.0
Upvotes: 1
Views: 245
Reputation:
After a little research I can explain what causes this behavior. T
is implicitly expanded to the union type isEqual<string|number>(a: string|number, b: string:number)
. I can't tell you why, but it is described on github.
From the example in the github comment above, I extracted a solution (or rather a hack) by using a phantom type P
:
type __R<T, T> = T;
type _R<T> = __R<*, T>;
type _Eq<T, U: _R<T>> = (T, U) => boolean;
type Eq<P> = _Eq<*, *>;
const eq:Eq<any> = (a, b) => a === b;
eq(true, false); // type checks
eq(1, 2); // type checks
eq(true, "foo"); // doesn't type check
There is probably a less messy solution but it is still a pity that flow doesn't just unify type variables with the same name and within the same scope with the same type.
Upvotes: 1