如何在TypeScript中获取联合类型的有效组合?
如何在TypeScript中生成符合逻辑的年龄组合联合类型
问题背景
我定义了以下几个表示孩子数量和年龄区间的联合类型:
type NumberOfChildren = "0" | "1" | "2" | "3+" type EldestAge = "-1" | "0-3" | "3-10" | "11-17" | "18+" // -1代表无对应值 type NextEldestAge = "-1" | "0-3" | "3-10" | "11-17" | "18+" // -1代表无对应值
如果直接用${NumberOfChildren}_${EldestAge}_${NextEldestAge}拼接,会产生很多不符合逻辑的无效组合:
0_0-3_-1:没有孩子却存在最大孩子年龄2_3-10_18+:次年长孩子的年龄大于最大孩子的年龄
我曾尝试用条件类型实现,但最终只得到了"0_-1_-1"这一种结果:
type combos<count extends string, age1 extends string, age2 extends string> = | ([count, age1, age2] extends ["0", "-1", "-1"] ? "0_-1_-1" : "0_-1_-1") | ([1, age1, -1] extends ["1", age1, "-1"] ? `1_${age1}_-1` : "0_-1_-1") // ... 更多组合
正确实现方案
通过递归条件类型结合数组顺序约束,可以生成所有符合逻辑的有效组合:
type NumberOfChildren = "0" | "1" | "2" | "3+" // 用数组定义年龄区间,保持从无值到年长的顺序 type AgeGroups = ["-1", "0-3", "3-10", "11-17", "18+"] // -1代表无对应值 // 递归生成符合年龄顺序的组合:次年长年龄 ≤ 最大年龄 type Builder<Age extends string, AgeGroup extends string[], Previous extends string[] = []> = AgeGroup extends [infer Head extends string, ...infer Tail extends string[]] ? `${Age}_${Head}_${Exclude<Head | Previous[number], "-1">}` | Builder<Age, Tail, [...Previous, Head]> : never; // 分情况定义不同孩子数量的有效组合 type ZeroChildren = `0_-1_-1`; // 0个孩子:只能是0_-1_-1 type OneChild = `1_${AgeGroups[number]}_-1`; // 1个孩子:次年长年龄固定为-1,最大年龄可选所有区间 type TwoChildren = Builder<"2", AgeGroups>; // 2个孩子:次年长年龄不大于最大年龄 type ThreeOrMoreChildren = Builder<"3+", AgeGroups>; // 3+个孩子:逻辑同2个孩子,次年长年龄不大于最大年龄 // 所有有效组合的联合类型 type ValidCombos = ZeroChildren | OneChild | TwoChildren | ThreeOrMoreChildren;
代码说明
- AgeGroups数组:通过数组顺序明确年龄区间的大小关系,为后续约束年龄顺序提供基础。
- Builder递归类型:遍历AgeGroups数组,对每个最大年龄(Head),只允许次年长年龄为之前遍历过的非-1区间(保证次年长年龄≤最大年龄),同时递归处理剩余区间。
- 分场景定义:针对不同孩子数量的逻辑单独处理,让类型更清晰:
- 0个孩子:仅有一种合法组合
- 1个孩子:次年长年龄必须为-1
- 2个及以上孩子:通过Builder保证年龄顺序的合法性
内容的提问来源于stack exchange,提问作者Tim Reistetter
相关产品推荐
相关产品推荐

