Sorry for the vague title, but I don't know how to express this problem concisely.
Basically, I have the following code (with unimportant bits removed):
function identity<T>(value: T): T {
return value;
}
function extent<T, K>(
values: T[],
map: (value: T) => K = identity // the '= identity' part gives an error
): [K, K] | undefined {
let min;
let max;
// ... stuff ...
return min === undefined || max === undefined ? undefined : [map(min), map(max)];
}
Where the default = identity
value results in a compiler error.
I can remove the default value for the map
parameter from the extent
's signature and always provide one myself:
extent([5, 1, 3, 4, 8], x => x)
Which will work just fine, but I'd rather not supply the second parameter, unless I'm actually mapping the values from one type to another.
How do I type the indentity
function so that it's accepted as the default value for extent
's map
parameter? I'm stuck on TypeScript 3.6 for the time being, if that matteres.
Probably the best way to deal with this that maintains type-safety to the outside world is via overloads:
function extent<T>(values: T[]): [T, T] | undefined
function extent<T, K>(values: T[], map: (value: T) => K): [K, K] | undefined
function extent<T, K>(
values: T[],
map?: (value: T) => K
): [K, K] | [T, T] | undefined {
const actualMap = map ?? identity;
let min;
let max;
// ... stuff ...
return min === undefined ||
max === undefined ?
undefined :
[actualMap(min), actualMap(max)];
}