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

如何用TypeScript提取类型泛型参数并生成Permission对象?

如何从Operation类型自动推导泛型参数生成Permission对象?

背景

TypeScript提供了ReturnType这类实用的类型工具,例如:

let target: ReturnType<typeof AcceptTerms>;

其中AcceptTerms是一个返回Operation<AcceptTermsParams, string>类型的函数。我希望提取Operation的泛型参数,并将其应用到同结构的Permission类型上,实现自动为所有Operation生成对应的Permission对象。

相关类型定义

type Permission<I, O> = {
    name: string;
    operationName: string;
    policies: Policy[]; // 假设已存在Policy类型定义
    // ...其他属性
}

type Operation<I, O> = {
    name: string;
    // ...其他属性
};

当前手动实现方式

目前我只能手动声明Permission的泛型参数来创建实例:

const allowViewAvailableBasketsForAll: Permission<void, Basket[]> = {
    name: "Allow view available baskets for all",
    operationName: VIEW_AVAILABLE_BASKETS_NAME,
    policies: [allowAllPolicy()],
};

期望实现的函数

我希望实现一个无需手动传入泛型参数I和O的工具函数,让TypeScript自动从Operation<I, O>类型中推导这两个参数:

export const withAllowAllFor = <??如何提取Operation的泛型参数??>(name: string): Permission<I, O> => ({
    name: `Allow ${name} for all`,
    operationName: name,
    policies: [allowAllPolicy()],
});

核心需求是:能否直接从Operation<I, O>类型中推导泛型参数,而非手动声明<I, O, T extends Operation<I, O>>?


解决方案

方式一:通过返回Operation的函数自动推导

利用TypeScript的infer关键字提取Operation的泛型参数,同时让函数接收返回Operation的函数作为入参,实现自动类型推导:

// 类型工具:提取Operation的泛型参数I和O
type ExtractOperationParams<T> = T extends Operation<infer I, infer O> ? { I: I; O: O } : never;

// 工具函数:接收返回Operation的函数,自动推导泛型参数
export const withAllowAllFor = <T extends (...args: any[]) => Operation<any, any>>(
  operationFn: T
): Permission<ExtractOperationParams<ReturnType<T>>['I'], ExtractOperationParams<ReturnType<T>>['O']> => {
  const operation = operationFn();
  return {
    name: `Allow ${operation.name} for all`,
    operationName: operation.name,
    policies: [allowAllPolicy()],
  };
};

// 使用示例
const allowAcceptTermsForAll = withAllowAllFor(AcceptTerms);

方式二:通过名称-类型映射表推导

如果只能传入operationName字符串,可先定义一个名称到Operation类型的映射表,让TypeScript根据名称自动关联对应的类型:

// 定义所有Operation名称与对应类型的映射
interface OperationMap {
  [VIEW_AVAILABLE_BASKETS_NAME]: Operation<void, Basket[]>;
  [ACCEPT_TERMS_NAME]: Operation<AcceptTermsParams, string>;
  // 补充其他Operation的映射关系
}

// 类型工具:提取Operation的泛型参数I和O
type ExtractOperationParams<T> = T extends Operation<infer I, infer O> ? { I: I; O: O } : never;

// 工具函数:根据operationName自动推导泛型参数
export const withAllowAllFor = <K extends keyof OperationMap>(
  operationName: K
): Permission<ExtractOperationParams<OperationMap[K]>['I'], ExtractOperationParams<OperationMap[K]>['O']> => ({
  name: `Allow ${operationName} for all`,
  operationName,
  policies: [allowAllPolicy()],
});

// 使用示例
const allowViewBasketsForAll = withAllowAllFor(VIEW_AVAILABLE_BASKETS_NAME);

这两种方式都不需要手动声明泛型参数I和O,TypeScript会自动通过类型推导完成泛型参数的提取与应用。


内容的提问来源于stack exchange,提问作者Adam A

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:10:24