TypeScript中如何正确提取泛型函数的参数类型
问题场景
- 常规场景下,提取TypeScript类中方法的参数类型,直接使用内置
Parameters工具类型即可,示例写法:
get = (...params: Parameters<Controller["get"]>) => {}
- 上述写法对签名固定、无泛型的方法(比如
get(id: number))可以正常生效,但面对泛型方法时会出现类型推断错误。 - 待提取参数的泛型方法签名示例:
functionName<T>(callback: () => Promise<T>)
- 直接使用
Parameters提取这类泛型方法的参数时,泛型参数T会被默认推断为never,且无法通过Parameters<Controller["get"]<T>>这类写法直接传入自定义泛型,最终拿到的参数类型不符合预期。
最小可复现代码:
class Test { genericFunction<T>(obj: T): T {return obj;} genericFunctionPromise<T>(c: () => Promise<T>): Promise<T> {return c();} example(params: Parameters<Test["genericFunction"]>) {}; examplePromise(params: Parameters<Test["genericFunctionPromise"]>) {params}; }
类型推断异常截图:

解决方案
出现这个问题的核心原因是:直接引用泛型方法但不传入具体泛型参数时,TypeScript会对无额外约束的泛型参数做默认填充,没有上下文的情况下T会被推断为never,自然无法得到正确的参数类型。
解决思路很简单:把参数提取的逻辑也声明为泛型,在实际使用时传入你需要的具体类型T,先将泛型方法特化为类型固定的具体方法,再调用Parameters提取参数即可。
适配后的写法如下:
class Test { genericFunction<T>(obj: T): T {return obj;} genericFunctionPromise<T>(c: () => Promise<T>): Promise<T> {return c();} // 将方法本身声明为泛型,传入T后先特化泛型方法,再提取参数 example<T>(params: Parameters<Test["genericFunction"]<T>>) { // 此处params类型自动推断为 [obj: T] }; examplePromise<T>(params: Parameters<Test["genericFunctionPromise"]<T>>) { // 此处params类型自动推断为 [c: () => Promise<T>] console.log(params) }; } // 调用时泛型会自动推断,无需手动指定 new Test().example("test") // 自动推断T为string,参数obj类型为string new Test().examplePromise(async () => 123) // 自动推断T为number,回调返回值类型为Promise<number>
对应最开始的箭头函数包装场景,写法如下:
class Controller { get<T>(callback: () => Promise<T>): Promise<T> { return callback() } } // 包装函数声明为泛型,传入T后特化类方法再提取参数 const getWrapper = <T,>(...params: Parameters<Controller["get"]<T>>) => { const controller = new Controller() return controller.get(...params) } // 调用时类型自动推断 getWrapper(async () => "hello") // T推断为string,返回值为Promise<string>
注意:该写法要求TypeScript版本 ≥ 4.7,低版本TypeScript不支持直接为泛型函数类型传入类型参数做特化,建议升级TypeScript版本后使用。
内容的提问来源于stack exchange,提问作者OSA413
相关产品推荐
相关产品推荐

