While playing with FP in Typescript I moved to overloaded functions and now have a problem of Typescript not detecting the correct overloaded parameter types.
/** parses as `Date` instance */
export function asDate(val: string | number | Date): Date;
export function asDate(val: string | number | Date | null | undefined): Date | null;
export function asDate(val: unknown) {
return val instanceof Date ? val : typeof val === 'number' || typeof val === 'string' ? new Date(val) : null;
}
export function apply<T, R>(fn: (arg: T) => R) {
return fn;
}
const date0 = asDate(123); // detected as Date
const date1 = apply(asDate)(123); // detected as Date | null
I would expect date1
to infer that it is called with a number
and detect return type Date
but it takes the most open type and detects Date | null
instead. Is there a way to fix it?
Actually, it is possible although I'm not quite sure why your approach does not work.
It works by letting the compiler infer the type of the passed function:
export function apply<F extends (args: any) => any>(fn: F) {
return fn;
}
In the end:
/** parses as `Date` instance */
export function asDate(val: string | number | Date): Date;
export function asDate(val: null | undefined): null;
export function asDate(val: unknown) {
return val instanceof Date ? val : typeof val === 'number' || typeof val === 'string' ? new Date(val) : null;
}
export function apply<F extends (args: any) => any>(fn: F) {
return fn;
}
const date0 = asDate(123); // detected as Date
const date1 = apply(asDate)(123); // detected as Date
const date3 = apply(asDate)(null); // detected as null
const date4 = apply(asDate)(true); // TS2769: No overload matches this call