I know there are numerous issues on StackOverflow about conditionally optional types in TypeScript, but none answered my question.
I have the following sum() function that takes an array and a callback. The callback should be optional only if the array is number[].
function sum<T>(iter: T[], callback?: (arg: T) => number): number {
return callback
? iter.reduce((sum, element) => sum + callback(element), 0)
: iter.reduce((sum, x) => sum + Number(x), 0); // <- I want to get rid of Number()
}
While this code works, it implies that any T could be converted to a number (which I don't want), while when T is a number, it does a redundant cast.
My best attempt at fixing this with overloads is:
type OptionalIfNumber<T, U> = T extends number ? U | undefined : U;
export function sum(iter: number[], callback?: undefined): number;
export function sum<T>(iter: T[], callback: (arg: T) => number): number;
export function sum<T>(iter: T[], callback: OptionalIfNumber<T, (arg: T) => number>): number {
return callback
? iter.reduce((sum, element) => sum + callback(element), 0)
: iter.reduce((sum, x) => sum + x, 0); // <- Problem is here
}
It seems that TypeScript does not know that the only time callback is undefined, T must extend number.
Is what I'm trying to do possible?