如何用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
相关产品推荐
相关产品推荐

