TypeScript:如何获取Cascade类型子键?为何推导结果不符合预期?
问题原因与修复方案
为什么ChildKey不是'childGeoList'?
原Cascade类型的第二个泛型参数T带有循环约束 T extends Cascade<C, T>,这会导致TypeScript在执行类型推断时陷入循环依赖:要验证T是否符合Cascade<C, T>的约束,必须先确定C的值;但C又需要从T的结构中反向推断,这种循环让TypeScript无法锁定具体的K值,最终只能将其推断为宽泛的string类型,而非预期的'childGeoList'。
另外原代码中code: Number存在小问题,Number是构造函数类型,业务场景中通常应使用原始数值类型number。
修复方案
方案一:移除循环约束,简化Cascade定义
直接去掉T的循环继承约束——我们的核心需求只是给类型添加一个可选的子键数组字段,无需强制循环约束:
type Cascade<C extends string, T> = Partial<Record<C, T[]>> interface AreaItem extends Cascade<'childGeoList', AreaItem> { name: string code: number } type ChildKey = AreaItem extends Cascade<infer K, infer _> ? K : never // 此时ChildKey的类型为'childGeoList'
方案二:保留层级语义的递归定义(可选)
如果需要明确表达“层级嵌套”的语义,可以用交叉类型替代循环约束,避免推断冲突:
type Cascade<C extends string, T> = Partial<Record<C, T[]>> & T // 定义基础区域类型 type AreaBase = { name: string code: number } // 递归构造带子节点的区域类型 type AreaItem = Cascade<'childGeoList', AreaBase> type ChildKey = AreaItem extends Cascade<infer K, infer _> ? K : never // ChildKey的类型为'childGeoList'
内容的提问来源于stack exchange,提问作者Jowei
相关产品推荐
相关产品推荐

