TypeScript调用泛型函数时保留类型参数的实现方案
实现支持动态泛型参数的带Modifier函数
原有代码背景
先看基础的类型定义与包装函数:
type GenericFunc<T> = () => Promise<T> interface FuncWithModifier<T> extends GenericFunc<T> { modifier: GenericFunc<T> } const wrapFunction = <T> (func: GenericFunc<T>): FuncWithModifier<T> => { const modifier: GenericFunc<T> = async () => func() return Object.assign(func, { modifier }) }
这段代码可以创建绑定固定类型T的带modifier的函数,但无法实现调用时动态指定泛型参数的需求。
需求目标
我们需要创建一个泛型函数,支持以下调用方式:
const unknown1: unknown = await genericFunc() const unknown2: unknown = await genericFunc.modifier() const num1: number = await genericFunc<number>() const num2: number = await genericFunc.modifier<number>() const bool1: boolean = await genericFunc<boolean>() const bool2: boolean = await genericFunc.modifier<boolean>()
即主函数和modifier都能在调用时动态指定返回值类型,而非绑定固定的T。
解决方案
核心思路是:将GenericFunc定义为自身支持泛型参数的函数类型,而非依赖外部绑定的T。调整后的代码如下:
1. 重新定义类型
// 定义自身可接收泛型参数的函数类型,默认类型为unknown type GenericFunc = <T = unknown>() => Promise<T>; // 带modifier的函数类型,modifier同样是可动态指定泛型的函数 interface FuncWithModifier extends GenericFunc { modifier: GenericFunc; }
2. 调整包装函数实现
const wrapFunction = (func: () => Promise<any>): FuncWithModifier => { // modifier作为泛型函数,调用时将结果断言为指定的T const modifier: GenericFunc = async <T = unknown>() => func() as Promise<T>; // 主函数同理,支持动态指定返回类型 const wrappedFunc: GenericFunc = async <T = unknown>() => func() as Promise<T>; // 为函数添加modifier属性并返回 return Object.assign(wrappedFunc, { modifier }); };
3. 创建目标泛型函数
const genericFunc = wrapFunction(async () => null as any);
验证调用
此时即可按照需求调用:
const unknown1: unknown = await genericFunc(); const unknown2: unknown = await genericFunc.modifier(); const num1: number = await genericFunc<number>(); const num2: number = await genericFunc.modifier<number>(); const bool1: boolean = await genericFunc<boolean>(); const bool2: boolean = await genericFunc.modifier<boolean>();
原理说明
原有代码的问题在于FuncWithModifier<T>将泛型T绑定到了整个接口上,导致每个实例只能对应一个固定类型。调整后,我们让主函数和modifier本身成为独立的泛型函数,允许在调用时动态传入类型参数,从而实现了灵活的类型指定能力。
内容的提问来源于stack exchange,提问作者Flo Edelmann
相关产品推荐
相关产品推荐

