如何在TypeScript重载函数中使用Parameters类型?
如何提取TypeScript重载函数中特定参数个数的签名参数
这确实是TypeScript里处理重载函数时的一个常见痛点——内置的Parameters工具类型默认只会提取最后一个重载签名的参数类型,这在使用像jQuery的.on()这类第三方库重载函数时,很容易拿到不符合预期的参数类型。不过我们可以通过自定义类型工具来精准筛选目标重载的参数。
先确认问题场景
就像你测试的那样,当函数存在多个重载时,Parameters<typeof func>总是返回最后声明的重载参数:
// 先声明两个重载 declare function foo(a: string, b: number): void; declare function foo(a: boolean, b: string, c: string): void; // 默认取最后一个重载的参数元组 type DefaultParams = Parameters<typeof foo>; // [boolean, string, string]
如果调换重载声明顺序,结果也会跟着取最后一个:
declare function foo(a: boolean, b: string, c: string): void; declare function foo(a: string, b: number): void; type DefaultParams = Parameters<typeof foo>; // [string, number]
解决方案:自定义类型工具匹配参数个数
我们可以写一个递归的自定义类型,通过参数长度来筛选目标重载签名。下面是实现代码:
// 辅助类型:移除函数的第一个重载签名 type OmitFirstOverload<T> = T extends { (...args: infer A): infer R; (...args: any[]): any; } ? ((...args: A) => R extends T ? never : T) extends { (...args: any[]): any; (...args: infer B): infer R; } ? (...args: B) => R : never : never; // 核心类型:提取指定参数个数的重载的参数元组 type ParametersOverload<F extends (...args: any[]) => any, N extends number> = F extends { (...args: infer P): any; (...args: any[]): any } ? P['length'] extends N ? P : ParametersOverload<OmitFirstOverload<F>, N> : never;
使用示例
针对你的foo函数,提取参数个数为2的重载参数:
declare function foo(a: string, b: number): void; declare function foo(a: boolean, b: string, c: string): void; // 获取参数个数为2的重载参数 type TwoArgParams = ParametersOverload<typeof foo, 2>; // [string, number] type aType = TwoArgParams[0]; // string type bType = TwoArgParams[1]; // number // 获取参数个数为3的重载参数 type ThreeArgParams = ParametersOverload<typeof foo, 3>; // [boolean, string, string]
对于jQuery的.on()函数(简化模拟):
// 模拟jQuery.on()的重载 declare function on(event: string, handler: () => void): void; declare function on(event: string, selector: string, handler: () => void): void; declare function on(eventMap: Record<string, () => void>): void; // 提取参数个数为3的重载参数 type OnThreeArgParams = ParametersOverload<typeof on, 3>; // [string, string, () => void]
工作原理
ParametersOverload会递归遍历函数的重载签名,每次检查当前第一个重载的参数长度是否匹配目标N;- 如果匹配,直接返回该重载的参数元组;如果不匹配,就用
OmitFirstOverload移除当前第一个重载,继续检查剩余的重载; - 如果遍历完所有重载都没有匹配的参数个数,会返回
never,你可以根据需求添加默认处理逻辑。
内容的提问来源于stack exchange,提问作者Weffe
相关产品推荐
相关产品推荐

