You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:32:06