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

TypeScript中如何实现操作与对应输入匹配的泛型execute函数?

TypeScript泛型函数实现操作与输入的严格类型约束

首先是你定义的类型:

export interface TypedDocumentNode<R, V> {}

type ClaimResult = {
  id: string;
  status: string;
};

type ClaimInput = {
  code: string;
};

type ResetResult = {
  id: string;
  userId: string;
};

type ResetInput = {
  email: string;
};

type Operations = {
  Claim: TypedDocumentNode<ClaimResult, ClaimInput>;
  Reset: TypedDocumentNode<ResetResult, ResetInput>;
};

你需要编写泛型函数execute,要求接收Operations的key作为操作名称,同时传入对应操作的输入变量,返回匹配的结果。合法调用示例:

// 合法调用
execute('Reset', { email: 'test@test.io' });
execute('Claim', { code: 'test-unique-code' });

但你当前的函数定义允许不匹配的输入(比如给Claim传入Reset的参数结构),当前定义如下:

export async function execute<
  Operation extends keyof typeof Operations,
  Document extends Documents[Operation],
  TResult extends Document extends TypedDocumentNode<infer X, any> ? X : never,
  TVariables extends Document extends TypedDocumentNode<TResult, infer V> ? V : never,
> (
  operation: Operation,
  variables?: TVariables
): Promise<TResult> {

  // 函数实现部分
}

解决方案

完全可以实现严格的类型约束,核心是通过索引访问类型+条件类型提取,直接关联操作名称对应的结果和输入类型,不需要多余的泛型参数。

简化版实现

export async function execute<Op extends keyof Operations>(
  operation: Op,
  variables: Operations[Op] extends TypedDocumentNode<infer R, infer V> ? V : never
): Promise<Operations[Op] extends TypedDocumentNode<infer R, infer V> ? R : never> {
  // 函数实现部分,根据实际逻辑替换返回值
  return {} as any;
}

可读性优化版(用辅助类型拆分)

// 辅助类型:根据操作名称提取对应结果类型
type OpResult<Op extends keyof Operations> = 
  Operations[Op] extends TypedDocumentNode<infer R, any> ? R : never;

// 辅助类型:根据操作名称提取对应输入类型
type OpVariables<Op extends keyof Operations> = 
  Operations[Op] extends TypedDocumentNode<any, infer V> ? V : never;

export async function execute<Op extends keyof Operations>(
  operation: Op,
  variables: OpVariables<Op>
): Promise<OpResult<Op>> {
  // 函数实现部分,根据实际逻辑替换返回值
  return {} as any;
}

为什么之前的定义失效?

你之前的泛型参数TVariables extends ...是类型约束而非精确类型,TypeScript允许子类型赋值,导致不匹配的输入可能绕过检查。直接用条件类型返回精确的输入类型,而非约束,就能确保传入的变量必须完全匹配对应操作的输入结构。

测试非法调用会触发TypeScript错误(符合预期):

// 报错:类型"{ email: string; }"的参数不能赋给类型"ClaimInput"的参数
execute('Claim', { email: 'test@test.io' });

合法调用则完全正常:

// 无错误
execute('Reset', { email: 'test@test.io' });
execute('Claim', { code: 'test-unique-code' });

内容的提问来源于stack exchange,提问作者Harshal Patil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:40:01