TypeScript中能否获取函数传入特定参数值时的返回类型?
能否获取函数传入特定参数值时的返回类型?
这个问题出现在使用生成式API的场景中,示例代码如下:
import { paths } from "./the-generated-types"; import createClient from "openapi-fetch"; const client = createClient<paths>(); // 可直接这样使用客户端 client.GET("/blogposts/{post_id}", { params: { path: { post_id: "my-post" }, query: { version: 2 }, }, }); // 但为了代码模块化,希望定义如下接口函数 export async function getBlogPostById(args: ??) : Promise<???> { }
为便于演示,我准备了简化的类型定义:
type Paths = "/a" | "/b" | "/c"; type PathToMethodMap = { "/a": { GET: (query: { search: string }) => { id: string; value: string }; }, "/b": { GET: (query: { search: string }) => { id: string; value: string }; }, "/c": { GET: (query: { search: string }) => { id: string; value: string }; PATCH: (body: { id: string, value: string }) => { id: string; value: string }; } }; function getClient<T extends Paths>(path: T): PathToMethodMap[T] { // 函数实现 } // 调用示例 getClient("/a").GET({ search: "hello" }); getClient("/c").PATCH({ id: "a", value: "b" });
我知道可以通过硬写类型路径实现目标函数:
function patchC(...args: Parameters<PathToMethodMap["/c"]["PATCH"]>): ReturnType<PathToMethodMap["/c"]["PATCH"]> { // 函数实现 }
但实际项目中这类类型定义复杂繁琐,我希望能用类似下面的写法:
function alternativePatchC(...args: Parameters<typeof getClient[传入"/c"时]["PATCH"]>) : ReturnType<typeof getClient[传入"/c"时]["PATCH"]>{ }
请问这种写法可行吗?
回答
这种写法不可行,但可以通过TypeScript的泛型和类型工具实现更简洁的等价效果,无需硬写冗长的类型路径。
核心方案:利用泛型推导调用后的类型
TypeScript不支持直接在类型层面模拟函数调用(比如typeof getClient[传入"/c"时]这种语法),但可以通过ReturnType工具类型获取函数调用后的返回类型,再结合泛型参数复用逻辑:
// 提取getClient传入指定路径后的返回类型 type ClientForPath<P extends Paths> = ReturnType<typeof getClient<P>>; // 封装参数和返回值的提取工具 type MethodParams<P extends Paths, M extends keyof ClientForPath<P>> = Parameters<ClientForPath<P>[M]>; type MethodReturn<P extends Paths, M extends keyof ClientForPath<P>> = ReturnType<ClientForPath<P>[M]>; // 简洁定义目标函数 function alternativePatchC(...args: MethodParams<"/c", "PATCH">): MethodReturn<"/c", "PATCH"> { return getClient("/c").PATCH(...args); }
针对openapi-fetch场景的适配
回到你最初的生成式API场景,同样可以用泛型复用自动生成的paths类型:
import { paths } from "./the-generated-types"; import createClient from "openapi-fetch"; const client = createClient<paths>(); // 提取指定路径+方法的请求参数类型 type RequestParams<Path extends keyof paths, Method extends keyof paths[Path]> = Parameters<typeof client[Method]<Path>>[1]; // 提取指定路径+方法的响应返回类型(处理异步Promise) type ResponseData<Path extends keyof paths, Method extends keyof paths[Path]> = Awaited<ReturnType<typeof client[Method]<Path>>>; // 模块化接口函数定义 export async function getBlogPostById(args: RequestParams<"/blogposts/{post_id}", "GET">): Promise<ResponseData<"/blogposts/{post_id}", "GET">> { return client.GET("/blogposts/{post_id}", args); }
为什么原写法不可行
typeof getClient获取的是函数本身的类型,而非调用后的返回类型。TypeScript没有语法支持直接在类型中“模拟传入特定参数并获取返回值”,但通过ReturnType<typeof getClient<"/c">>可以间接实现这一效果,这也是上述方案的核心逻辑。
内容的提问来源于stack exchange,提问作者dwjohnston
相关产品推荐
相关产品推荐

