'Typescript equal generics "No overload matches this call"
So, I'm building a TypeScript application and I'm having issues with generics and overload. Here's a minimal example of my code:
function isEqual(data: string, value: string): boolean;
function isEqual(data: number, value: number): boolean;
function isEqual(data: boolean, value: boolean): boolean;
function isEqual(data: unknown, value: unknown): boolean {
return data === value;
}
function compareVals<ValueType>(
option: ValueType,
value: ValueType,
) {
return isEqual(option, value);
^^^^^
// No overload matches this call.
// Overload 1 of 3, '(data: string, value: string): boolean', gave the following error.
// Argument of type 'ValueType' is not assignable to parameter of type 'string'.
// Overload 2 of 3, '(data: number, value: number): boolean', gave the following error.
// Argument of type 'ValueType' is not assignable to parameter of type 'number'.
// Overload 3 of 3, '(data: boolean, value: boolean): boolean', gave the following error.
// Argument of type 'ValueType' is not assignable to parameter of type 'boolean'.
}
const equal = compareVals<number>(1,1); // equal: boolean
const equal2 = compareVals<boolean>(true, false); // equal2: boolean
I don't understand why TS doesn't use the same type. I also tried
...
function compareVals<ValueType extends string | number | boolean>(
...
to try forcing ValueType as one of the overload types but it got the same error.
I feel that I'm missing something pretty basic here.
Solution 1:[1]
ValueType is defined like this: ValueType extends string | number | boolean
Typescript can't infer the type of the values when they get to isEqual, because either one could be any of the three you defined. Therefore the function signature of compareVals doesn't match any of the isEqual signatures you've defined.
If I understand your intent, you could make isEqual generic, and specify that the types in isEqual will be the same.
function isEqual<T>(data: T, value: T): boolean {
return data === value;
}
function compareVals<ValueType extends string | number | boolean>(
option: ValueType,
value: ValueType,
) {
return isEqual<ValueType>(option, value);
}
ValueType is passed to isEqual, so it knows what to expect.
compareVals<number>(1, 1); // types check out
compareVals<boolean>(true, 1); // complains about 1: Argument of type 'number' is not assignable to parameter of type 'boolean'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Abe |
