如何在TypeScript中创建带条件约束的递归层级接口?
TypeScript递归条件图层接口实现方案
1. 定义基础枚举与映射类型
先明确图层组、单个图层的名称枚举,以及单个图层对应的code枚举:
// 图层名称枚举:包含组和单个图层 enum LayerName { // 图层组 AG = "AG", OG = "OG", Arkaplan = "Arkaplan", // 单个图层 Road = "Road", Building = "Building", Tree = "Tree" } // 单个图层对应的code枚举 enum RoadCode { MainRoad = "MAIN_ROAD", SideRoad = "SIDE_ROAD" } enum BuildingCode { Residential = "RESIDENTIAL", Commercial = "COMMERCIAL" } enum TreeCode { Pine = "PINE", Oak = "OAK" } // 映射单个图层名称到对应的code类型 type LayerCodeMap = { [LayerName.Road]: RoadCode; [LayerName.Building]: BuildingCode; [LayerName.Tree]: TreeCode; }; // 提取图层组名称类型 type LayerGroupNames = LayerName.AG | LayerName.OG | LayerName.Arkaplan; // 提取单个图层名称类型(排除所有组名) type SingleLayerNames = Exclude<LayerName, LayerGroupNames>;
2. 实现递归条件接口
通过条件类型+映射类型,严格约束不同name对应的字段结构:
// 递归图层接口:根据name自动约束字段 type Layer = // 单个图层规则:必须有对应code,禁止subLayers { [K in SingleLayerNames]: { name: K; code: LayerCodeMap[K]; subLayers?: never; }; }[SingleLayerNames] | // 图层组规则:禁止code,必须有递归的subLayers数组 { [K in LayerGroupNames]: { name: K; code?: never; subLayers: Layer[]; }; }[LayerGroupNames];
3. 验证与使用示例
合法结构示例
const validLayerTree: Layer = { name: LayerName.AG, subLayers: [ { name: LayerName.Road, code: RoadCode.MainRoad }, { name: LayerName.OG, subLayers: [ { name: LayerName.Building, code: BuildingCode.Commercial }, { name: LayerName.Arkaplan, subLayers: [ { name: LayerName.Tree, code: TreeCode.Oak } ] } ] } ] };
非法结构会触发类型报错
- 图层组添加
code字段:// 报错:类型“{ name: LayerName.Arkaplan; code: string; subLayers: never[]; }”不能赋给类型“Layer” const invalidGroup: Layer = { name: LayerName.Arkaplan, code: "test", subLayers: [] }; - 单个图层缺少
code或添加subLayers:// 报错:缺少属性“code”,且类型“{ name: LayerName.Tree; subLayers: never[]; }”中不存在属性“code” const invalidSingle: Layer = { name: LayerName.Tree, subLayers: [] };
核心逻辑说明
- 用
{[K in 类型]: ...}[类型]的映射方式,为每个name值生成专属类型,确保name与code/subLayers的强绑定 - 通过
Exclude精准区分组和单个图层的名称范围 - 用
never明确禁止不符合规则的字段,让TypeScript在编写阶段就拦截错误 - 递归的
Layer类型支持任意层级的组嵌套
内容的提问来源于stack exchange,提问作者Sezerc
相关产品推荐
相关产品推荐

