编写TypeScript声明文件时能否约束数组内A/B/C连续按序出现?
TypeScript 实现数组内嵌固定连续
'A'|'B'|'C'序列约束的方案 当前TypeScript的类型系统完全可以实现你描述的约束规则,不需要依赖运行时校验,纯类型定义就能覆盖所有场景要求。
规则拆解
你需要的校验逻辑本质可以拆分为三点:
- 传入的数组结构中,必须存在连续的、顺序严格为
'A' -> 'B' -> 'C'的元素段 - 这一连续段可以出现在数组的任意位置(开头、中间、结尾)
- 连续段的前后可以搭配任意其他类型、任意数量的元素,无额外限制
实现逻辑
由于前后可搭配的元素组合是无限的,无法通过固定长度的元组类型穷举所有合法结构,需要用递归条件类型逐位扫描数组,检查是否存在匹配的连续子序列。
核心类型定义如下:
// 递归检查元组中是否存在连续的 'A' -> 'B' -> 'C' 子序列 type HasABCSequence<T extends unknown[]> = // 基准情况:数组长度不足3,直接判定不满足要求 T extends [unknown, unknown, unknown, ...infer _Rest] ? // 检查当前数组开头的三个元素是否恰好为严格顺序的A、B、C T extends ['A', 'B', 'C', ...unknown[]] ? true : // 不匹配则扔掉第一个元素,递归检查剩余的子数组 T extends [unknown, ...infer Rest extends unknown[]] ? HasABCSequence<Rest> : false : false; // 封装符合要求的数组类型:仅当元组存在连续ABC序列时才返回合法类型 type ArrayWithABC<T extends unknown[] = unknown[]> = HasABCSequence<T> extends true ? T : never;
实际使用
在你为外部库编写.d.ts声明时,直接将这个类型作为函数参数的泛型约束即可:
// 外部库函数的类型声明 declare function processLibInput<T extends unknown[]>( input: ArrayWithABC<T> ): void;
针对你给出的测试用例,类型校验的表现完全符合预期:
processLibInput(['A', 'B', 'C', 1, 2, 3]):识别到数组开头的连续ABC序列,校验通过processLibInput([1, 2, 'A', 'B', 'C', 3]):识别到数组中间的连续ABC序列,校验通过processLibInput([1, 'A', 2, 'B', 'C', 3]):A和B之间插入了数字2,不存在连续的ABC序列,校验直接报错processLibInput([1, 'C', 'A', 'B', 2, 3]):既无正确顺序、也无连续的ABC序列,校验报错
注意事项:这套约束基于TS对字面量元组的精确位置推导实现。如果传入的数组被推导为宽数组类型(比如显式标注为
(string | number)[],丢失了元素的顺序、位置信息),类型校验会失效。日常调用时只要传入字面量形式的数组入参,TS会自动推导对应的元组结构,不需要额外的手动类型标注。
内容的提问来源于stack exchange,提问作者Aryan Deora
相关产品推荐
相关产品推荐

