如何实现TypeScript泛型convertDeepToShallow函数的类型定义?
实现
convertDeepToShallow泛型类型转换函数 需求概述
- 输入嵌套对象(如
{ a: { b: any } })时,输出需翻转嵌套层级:{ b: { a: any } } - 输入包含原始类型属性的混合对象(如
{ a: { b: any }, primitive: number })时,输出保留原始属性,同时翻转嵌套对象部分:{ b: { a: any }, primitive: number }
问题分析
你尝试的ConvertType无法同时兼容三种场景(纯嵌套对象、纯原始属性对象、混合对象),核心问题在于类型定义中错误复用泛型参数,导致嵌套翻转逻辑和原始属性保留逻辑无法正确联动。
解决方案
1. 定义基础类型边界
先明确原始类型和可翻转的嵌套对象范围:
type Primitive = string | number | boolean | null | undefined; // 筛选出值为非原始类型的嵌套对象 type NestedObj<T> = T extends Record<string, infer U> ? U extends Primitive ? never : T : never;
2. 实现核心转换类型
拆分出两个辅助类型,分别处理嵌套翻转和原始属性保留,最后合并结果:
// 翻转嵌套对象的层级:将外层键与内层键互换 type FlipNested<T extends Record<string, Record<string, any>>> = { [InnerKey in keyof T[keyof T]]: { [OuterKey in keyof T as T[OuterKey] extends Record<InnerKey, any> ? OuterKey : never]: T[OuterKey][InnerKey]; }; }; // 提取并保留对象中的原始类型属性 type KeepPrimitives<T> = { [K in keyof T as T[K] extends Primitive ? K : never]: T[K]; }; // 合并翻转后的嵌套部分与原始属性部分 type ConvertDeepToShallow<T> = T extends Record<string, any> ? FlipNested<Extract<T, Record<string, Record<string, any>>>> & KeepPrimitives<T> : T;
3. 函数类型定义与实现
type ConvertType = <T extends Record<string, Primitive | Record<string, any>>>(input: T) => ConvertDeepToShallow<T>; const converter: ConvertType = (input) => { const result: Record<string, any> = {}; for (const outerKey in input) { const value = input[outerKey]; // 处理嵌套对象,翻转层级 if (typeof value === 'object' && value !== null && !Array.isArray(value)) { for (const innerKey in value) { result[innerKey] = { [outerKey]: value[innerKey] }; } } else { // 直接保留原始类型属性 result[outerKey] = value; } } return result; };
测试验证
const convObj = converter({ gap: { md: '' } }); // 类型推断:{ md: { gap: string } } ✅ const convPrimitive = converter({ primitive: 2 }); // 类型推断:{ primitive: number } ✅ const convBoth = converter({ gap: { md: '' }, primitive: 1 }); // 类型推断:{ md: { gap: string } } & { primitive: number } ✅
内容的提问来源于stack exchange,提问作者Highmastdon
相关产品推荐
相关产品推荐

