如何基于嵌套字典结构的TypeScript接口动态声明同名键的类型?
如何基于嵌套字典结构的TypeScript接口动态声明同名键的类型?
我太懂这种需求了——硬抄内层类型定义不仅麻烦,以后原接口改了还要同步更新,完全是给自己挖坑!你已经走到一半了,再往前推一步就能搞定,我来给你拆解清楚。
首先先明确你的原接口结构:
export interface components { schemas: { Subscriber: { subscriber?: { subscriptions?: { [key: string]: { key1?: string; key2?: string; key3?: string; } } } } } }
你已经能通过components["schemas"]["Subscriber"]["subscriber"]拿到subscriber的类型,但因为subscriber和subscriptions都是可选属性(带?),直接访问深层属性会碰到undefined的干扰,而且我们最终要的是subscriptions里每个键对应的值类型。
这里的核心技巧是用TypeScript索引访问类型结合NonNullable处理可选属性,再用T[keyof T]提取对象的值类型。
分步实现方案
- 先去掉可选属性的
undefined干扰,拿到确定的subscriptions类型 - 提取
subscriptions中所有值的类型(也就是你要的Subscription)
具体代码如下:
// 第一步:拿到去掉undefined的subscriber类型,再取出subscriptions的类型 type Subscriptions = NonNullable<components["schemas"]["Subscriber"]["subscriber"]>["subscriptions"]; // 第二步:提取subscriptions的值类型,也就是目标Subscription type Subscription = NonNullable<Subscriptions>[keyof NonNullable<Subscriptions>];
简化写法(一行搞定)
如果觉得分步写太啰嗦,也可以把逻辑合并成一行,可读性也不差:
type Subscription = NonNullable< NonNullable<components["schemas"]["Subscriber"]["subscriber"]>["subscriptions"] >[keyof NonNullable< NonNullable<components["schemas"]["Subscriber"]["subscriber"]>["subscriptions"] >];
更优雅的复用方式
如果以后经常需要提取对象的值类型,可以定义一个通用工具类型:
// 通用工具类型:提取对象所有值的类型 type ValueOf<T> = T[keyof T]; // 用工具类型简化Subscription的定义 type Subscription = ValueOf< NonNullable< NonNullable<components["schemas"]["Subscriber"]["subscriber"]>["subscriptions"] > >;
为什么这能生效?
NonNullable<T>:把类型T中的undefined和null排除掉,因为你的subscriber和subscriptions都是可选的,直接访问会包含undefined,必须先排除才能安全访问深层属性。T[keyof T]:这是TypeScript提取对象值类型的经典技巧——keyof T会拿到对象T的所有键的联合类型,用这个联合类型去索引T,就会得到所有值的联合类型。在你的场景里,所有值的类型都是一样的,所以最终结果就是你要的单一类型。
这样一来,不管以后components接口里的最内层类型怎么改,Subscription都会自动同步更新,完全不用手动复制粘贴,完美实现动态推导的需求!
内容来源于stack exchange
相关产品推荐
相关产品推荐

