如何将值为泛型函数的对象泛型层级提升至对象级别?
将泛型函数对象转换为实例化泛型参数后的对象类型
假设我们有一个对象类型,其所有属性都是泛型函数:
type Have = { foo: <T>(dep: {dependency: (a:T, b:T) => T}) => (a:T) => T bar: <T>() => (a: T) => string }
我们需要生成一个带泛型参数的对象类型,其中每个属性都是原对象对应函数实例化该泛型参数后的类型,即:
type Want<T> = { foo: (dep: {dependency: (a:T, b:T) => T}) => (a:T) => T bar: () => (a: T) => string }
可以通过两个嵌套的类型工具实现这个转换:
ReplaceInType:递归替换类型中的指定泛型参数为目标类型InstantiateObj:遍历对象的每个属性,将泛型函数实例化为目标泛型参数后的类型
// 递归替换类型中的指定类型为目标类型 type ReplaceInType<Type, From, To> = Type extends From ? To : Type extends object ? { [K in keyof Type]: ReplaceInType<Type[K], From, To> } : Type; // 实例化对象中所有泛型函数的泛型参数为指定类型 type InstantiateObj<TObj, T> = { [K in keyof TObj]: TObj[K] extends <U>(...args: infer Args) => infer Ret ? (...args: ReplaceInType<Args, U, T>) => ReplaceInType<Ret, U, T> : TObj[K] };
使用示例
// 定义原对象类型 type Have = { foo: <T>(dep: {dependency: (a:T, b:T) => T}) => (a:T) => T bar: <T>() => (a: T) => string } // 生成目标类型 type Want<T> = InstantiateObj<Have, T>; // 测试实例化number类型 type WantNumber = Want<number>; // 等价于: // { // foo: (dep: { dependency: (a: number, b: number) => number; }) => (a: number) => number; // bar: () => (a: number) => string; // }
这个方案支持原对象中混合泛型和非泛型函数的情况,会自动保留非泛型函数的原有类型。
内容的提问来源于stack exchange,提问作者Glen Whitney
相关产品推荐
相关产品推荐

