TypeScript泛型无法从函数参数自动推断传入类型的问题咨询
问题描述
type Method = "get" | "post" | "put" | "patch" | "delete" | "head" | "options"; export interface TRoute<TMethod, TResponse = unknown, TParmas = undefined> { payload: { method: TMethod; url: string; }; } export const route = <TResponse, TMethod extends Method = Method>( method: TMethod, url: string ): TRoute<TMethod, TResponse> => ({ payload: { method, url }, }); const result = route<{ result: string[] }>("get", "/index")
实际类型推导结果
变量result的推导类型为:
const result: TRoute<Method, { result: string[]; }, undefined>
期望类型推导结果
const result: TRoute<"get", { result: string[]; }, undefined>
需求约束:不希望手动传入第二个泛型参数,需要TMethod的类型直接从传入的method实参中推断得到对应的字面量类型。
原因
TypeScript 目前不支持部分泛型参数推断:显式传入泛型列表中的部分参数时,剩余未手动传入的泛型不会再从函数实参推导,会直接使用预设的泛型默认值。
当前代码泛型顺序为<TResponse, TMethod extends Method = Method>,调用时手动传入了第一个泛型TResponse,未手动传入的TMethod直接命中默认值Method联合类型,不会从传入的"get"实参推断为字面量类型。
解决方案
用柯里化拆分泛型传入和实参传入的逻辑:外层函数接收需要手动指定的TResponse泛型,内层函数接收实际参数、自动推断TMethod类型,完全满足需求,修改后代码如下:
type Method = "get" | "post" | "put" | "patch" | "delete" | "head" | "options"; export interface TRoute<TMethod, TResponse = unknown, TParmas = undefined> { payload: { method: TMethod; url: string; }; } export const route = <TResponse = unknown>() => <TMethod extends Method>( method: TMethod, url: string ): TRoute<TMethod, TResponse> => ({ payload: { method, url }, }); // 调用时外层传入响应类型,内层传入接口参数,TMethod自动推断为"get" const result = route<{ result: string[] }>()("get", "/index")
此时result的推导类型完全符合预期:TRoute<"get", { result: string[] }, undefined>。
注:TypeScript 官方正在迭代部分泛型参数推断特性,特性正式上线后可无需修改调用写法直接实现需求,当前版本(5.x及以下)柯里化是兼容性最高的实现方案。
内容的提问来源于stack exchange,提问作者Abdollah Keshtkar
相关产品推荐
相关产品推荐

