You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript如何定义多个TimeSlotString拼接的递归字符串类型?

如何在TypeScript中定义多个TimeSlotString拼接的字符串类型?

问题背景

我正在开发一个类型安全的系统,用字符串表示时间段集合。已经通过模板字符串类型定义了单个时间段的格式:

export type Weekday = "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun";
export type TimeSlot = "08:00" | "08:30" | "09:00" | /*...*/ "19:30" | "20:00";
export type TimeSlotString = `|${Weekday}::${TimeSlot}|`;

现在需要定义多个TimeSlotString拼接后的字符串类型,比如符合"|mon::10:30||tue::14:30||wed::08:00|"格式的TimeSlotsConcat。但直接递归定义时出现循环引用错误:

type TimeSlotsConcat = "" | `${TimeSlotString}` | `${TimeSlotString}${TimeSlotsConcat}`;
// ❌ 错误:类型别名'TimeSlotsConcat'循环引用自身。

请问在TypeScript中是否可以实现这个类型?

解决方案

TypeScript中可以实现该类型,需要避开直接自引用导致的循环检测,以下是两种可行方案:

方案一:带递归深度控制的辅助类型(兼容TS 4.1+)

通过引入带参数的辅助类型,用数字限制递归次数,避免直接自引用:

// 辅助类型:生成0到指定数字的联合类型,用于控制递归深度
type NumbersUpTo<N extends number, T extends number[] = []> =
  T['length'] extends N ? T[number] : NumbersUpTo<N, [...T, T['length']]>;

// 辅助类型:递归拼接TimeSlotString,Acc为当前拼接结果
type RepeatTimeSlots<Count extends number, Acc extends string = ""> =
  Count extends 0
    ? Acc
    : Acc | RepeatTimeSlots<NumbersUpTo<Count>[number], `${Acc}${TimeSlotString}`>;

// 定义最多支持5个时间段的拼接类型(可修改数字调整上限)
type TimeSlotsConcat = RepeatTimeSlots<5>;

此方案可灵活控制允许的最大时间段数量,同时避免循环引用错误。

方案二:TS 4.5+简洁递归写法

TS 4.5及以上版本支持递归模板字符串,可通过间接递归的方式实现:

type TimeSlotsConcat = "" | `${TimeSlotString}${TimeSlotsConcat}`;

若仍触发循环引用错误,可通过条件类型绕开检测:

type TimeSlotsConcat = "" | (string extends "" ? never : `${TimeSlotString}${TimeSlotsConcat}`);

注意事项

  • TypeScript默认限制递归类型深度为100层,若需支持更多拼接,可通过--maxNodeModuleJsDepth编译选项调整,但过大的深度会影响类型检查性能。
  • 若不需要空字符串表示“无时间段”的情况,可直接移除""分支。

内容的提问来源于stack exchange,提问作者Felipe Chernicharo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:13:29