TypeScript中如何利用Split类型优化日期范围字符串解析方法?
利用TypeScript Split类型优化日期范围解析方法
先明确Split类型的作用
你提供的Split是TypeScript字符串字面量类型工具,能在编译期把字符串类型按指定分隔符拆分。比如:
Split<"12/2024", "/">→ 得到类型["12", "2024"]Split<"01/01/2024-12/31/2024", "-">→ 得到类型["01/01/2024", "12/31/2024"]
它的核心价值是帮你在类型层面约束输入格式,配合运行时逻辑,让代码更严谨。
第一步:用Split定义合法输入的类型约束
先基于Split和字符串模板类型,明确允许的输入格式,让TypeScript在编译期就拦截非法输入:
// 原Split类型 type Split<S extends string, D extends string> = string extends S ? string[] : S extends '' ? [] : S extends `${infer T}${D}${infer U}` ? [T, U] : [S]; // 基础数字字符串类型 type NumericStr = `${number}`; // 月年格式:MM/YYYY type MonthYear = `${NumericStr}/${NumericStr}`; // 完整日期格式:MM/DD/YYYY type FullDate = `${NumericStr}/${NumericStr}/${NumericStr}`; // 日期范围格式:MM/DD/YYYY-MM/DD/YYYY type DateRange = `${FullDate}-${FullDate}`; // 最终合法输入类型 type ValidDateInput = MonthYear | DateRange;
如果需要更严格的类型校验(比如月份必须是1-12),可以用Split进一步推导:
// 校验月年格式的合法性(类型层面) type ValidMonthYear<T extends MonthYear> = Split<T, "/"> extends [`${infer M extends number}`, `${infer Y extends number}`] ? M extends 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 ? Y extends number & { toString: () => `${number}${number}${number}${number}` } // 确保4位年份 ? T : never : never : never; // 示例:ValidMonthYear<"13/2024"> 会被推断为never,编译期报错
第二步:结合类型守卫重构解析函数
用类型守卫把运行时校验和类型系统对齐,让函数逻辑更清晰,同时保留原有的解析逻辑:
// 类型守卫:判断输入是否为月年格式 function isMonthYear(input: string): input is MonthYear { return /^\d{1,2}\/\d{4}$/.test(input); } // 类型守卫:判断输入是否为日期范围格式 function isDateRange(input: string): input is DateRange { const parts = input.split('-'); if (parts.length !== 2) return false; const [start, end] = parts; return /^\d{1,2}\/\d{1,2}\/\d{4}$/.test(start) && /^\d{1,2}\/\d{1,2}\/\d{4}$/.test(end); } // 重构后的解析函数 const parseDateRange = (range: ValidDateInput): Date | null => { if (!range) return null; // 处理月年格式 if (isMonthYear(range)) { const [month, year] = range.split('/').map(Number); // 增加月份合法性校验(避免0或13这类无效值) if (!isNaN(month) && !isNaN(year) && month >= 1 && month <= 12) { return new Date(year, month - 1); } } // 处理日期范围格式(和原逻辑一致,返回起始日期) if (isDateRange(range)) { const [startDateStr] = range.split('-'); const startDate = new Date(startDateStr); return isNaN(startDate.getTime()) ? null : startDate; } return null; };
优化后的优势
- 编译期校验:调用方传入非法格式(比如
"2024/12"或"01-01-2024")时,TypeScript会直接报错,提前避免运行时问题。 - 逻辑清晰:类型守卫把不同格式的判断和处理逻辑拆分,代码可读性更强。
- 扩展性好:如果以后要支持新格式(比如
YYYY-MM-DD),只需扩展ValidDateInput类型,再添加对应的类型守卫和处理逻辑即可。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

