如何将嵌套对象的函数键扁平化为单层TypeScript类型?
实现TypeScript嵌套对象的函数类型单层扁平化
问题场景
现有如下嵌套结构的对象:
const items = { get: (name: string) => '-' + name, log: () => { console.log('Hello') }, commands: { table: (name: string) => 'table-' + name, // 可扩展更多函数/嵌套对象 } // 可扩展更多函数/嵌套对象 }
需要将其类型扁平化为单层结构,只保留所有函数的键名和对应类型,最终目标类型如下:
interface Items { get: (name: string) => string; log: () => void; table: (name: string) => string; }
你当前尝试的递归映射类型无法实现扁平化:
type Mapped<T extends Record<string, any>> = { [K in keyof T]: T[K] extends Record<string, unknown> ? Mapped<T[K]> : T[K]; }; type Items = Mapped<typeof items>;
上述代码只会递归嵌套类型,不会将深层的键提升到顶层。
解决方案
可以通过递归提取所有函数键值对,再合并为单层类型的方式实现:
// 提取对象中所有非嵌套对象的键值对(即函数类型) type ExtractFunctions<T> = { [K in keyof T]: T[K] extends Record<string, unknown> ? never : T[K]; } extends infer U ? { [K in keyof U as U[K] extends never ? never : K]: U[K] } : never; // 递归提取所有层级的函数类型,再合并 type FlattenFunctions<T> = ExtractFunctions<T> & (T extends Record<string, infer V> ? FlattenFunctions<V> : never); // 最终生成单层扁平化类型 type Items = FlattenFunctions<typeof items>;
代码解释
ExtractFunctions<T>:遍历当前层级的键,过滤掉值为嵌套对象的键,只保留函数类型的键值对。通过never标记不需要的键,再重新构造过滤后的类型。FlattenFunctions<T>:先提取当前层级的函数类型,再递归处理当前层级中所有嵌套对象的函数类型,最后通过交叉类型(&)合并所有层级的键值对。TypeScript会自动将交叉类型合并为单层接口结构。
测试验证:Items类型最终会和目标接口完全一致,所有深层函数都会被提升到顶层。
内容的提问来源于stack exchange,提问作者Ewan
相关产品推荐
相关产品推荐

