TypeScript中组合重载函数时如何实现正确的类型推导?
解决TypeScript重载函数通过高阶函数传递后的类型推导问题
问题出在你定义的apply函数上:原apply用(arg: T) => R来约束传入的函数,TypeScript遇到重载函数时,会自动把所有重载签名合并成单一的宽泛签名——参数取所有重载参数的联合类型,返回值取所有返回值的联合类型。所以apply(asDate)得到的函数类型会变成(val: unknown) => Date | null,调用时自然只能推导出Date | null。
解决办法:让apply保留原函数的重载签名
修改apply的泛型定义,直接让它返回传入函数的原始类型,而不是强行转换成单签名函数:
/** 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; } // 修改后的apply,保留原函数的完整类型(包括重载) export function apply<T extends (...args: unknown[]) => unknown>(fn: T): T { return fn; } const date0 = asDate(123); // 类型:Date const date1 = apply(asDate)(123); // 类型:Date(符合预期) const date2 = apply(asDate)(null); // 类型:Date | null(正确匹配重载)
原理说明
当apply的泛型T被推断为asDate的完整重载类型时,返回T会直接保留所有重载签名。此时调用apply(asDate)(123),TypeScript会像直接调用asDate(123)一样,匹配对应的重载签名,正确推导出返回类型为Date。
如果需要更宽松的参数约束,也可以把unknown[]换成any[],效果一致。
内容的提问来源于stack exchange,提问作者Alex Rempel
相关产品推荐
相关产品推荐

