简体   繁体   中英

How to make a generic function with the arguments of the same type using Flow generics

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

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

Try it .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM