类型级字符串拆分
在类型系统中将字符串拆分为元组。
类型级字符串拆分 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。
模板字面量类型
类型系统可以使用模板字面量类型与infer进行组合,对字符串字面量类型执行模式匹配。这是进行类型级字符串解析的核心工具。
表示法:真实的 TypeScript 会使用由反引号包围、包含美元符号加大括号占位符的字符串来书写模板字面量类型。在这些代码片段中,我们将这种模式表示为 Tpl<...>,并按顺序列出每个部分;例如,匹配字面量前缀后跟 Rest 的反引号模板表示为 Tpl<'prefix', infer Rest>。
type StartsWithA<S> = S extends Tpl<'a', string> ? true : false;
// Tpl<'a', string> is a backtick template literal type: 'a' then anything
type X = StartsWithA<'abc'>; // true
type Y = StartsWithA<'bcd'>; // false推断后缀
将infer放在模板中,以捕获字符串的一部分。这里我们捕获开头为"a"之后的所有内容。
type AfterA<S> = S extends Tpl<'a', infer Rest> ? Rest : never;
// Tpl<'a', Rest> captures everything after a leading 'a'
type X = AfterA<'abc'>; // 'bc'按分隔符拆分
要在分隔符第一次出现的位置拆分字符串,请匹配“头部、分隔符、尾部”这一模式,并推断两侧的内容。第一次匹配会生效,因为对于头部,推断会从左侧进行贪婪匹配。
type SplitOnce<S, Sep extends string> =
S extends Tpl<infer Head, Sep, infer Tail>
? [Head, Tail]
: [S];
// Tpl<Head, Sep, Tail> matches up to the first separator
type X = SplitOnce<'a-b-c', '-'>; // ['a', 'b-c']递归拆分
要拆分出所有部分,请对尾部进行递归处理。将每个头部收集到元组中,直到不再有分隔符。
type Split<S extends string, Sep extends string> =
S extends Tpl<infer Head, Sep, infer Tail>
? [Head, ...Split<Tail, Sep>]
: [S];
// recurse on Tail until no separator remains
type X = Split<'a.b.c', '.'>; // ['a', 'b', 'c']跟踪递归过程
跟踪 Split<"a.b.c", ".">:
- 头部 "a",尾部 "b.c" -> ["a", ...Split<"b.c">]
- 头部 "b",尾部 "c" -> ["b", ...Split<"c">]
- "c" 中没有 ".",到达基本情况 -> ["c"]
结果:["a", "b", "c"]。
type X = Split<"one,two", ",">; // ["one", "two"]
type Y = Split<"x/y/z", "/">; // ["x", "y", "z"]处理空片段
当分隔符相邻或位于边缘时,拆分可能产生空字符串。该模式仍然可以匹配,并推断出空的Head或Tail。
type X = Split<"a,,b", ",">; // ["a", "", "b"]
type Y = Split<",a", ",">; // ["", "a"]重新拼接
拆分的逆操作是拼接:遍历字符串元组,并使用模板字面量和分隔符将它们连接起来。它与拆分天然配对。
type Join<T extends string[], Sep extends string> =
T extends [infer H extends string, ...infer R extends string[]]
? R extends [] ? H : Tpl<H, Sep, Join<R, Sep>>
: '';
// Tpl<...> denotes a template literal type concatenation
type X = Join<['a', 'b', 'c'], '-'>; // 'a-b-c'修剪空白
字符串工具可以组合使用。Trim类型通过模板推断反复移除空格,从而删除开头和结尾的空格。
type TrimLeft<S extends string> =
S extends Tpl<' ', infer R> ? TrimLeft<R> : S;
type TrimRight<S extends string> =
S extends Tpl<infer R, ' '> ? TrimRight<R> : S;
type Trim<S extends string> = TrimRight<TrimLeft<S>>;
// Tpl<' ', R> strips a leading space; Tpl<R, ' '> strips a trailing one
type X = Trim<' hi '>; // 'hi'替换子字符串
替换的实现方式是围绕目标内容进行拆分,然后使用替换内容重新拼接,整个过程都通过模板推断和递归完成。
type ReplaceAll<S extends string, From extends string, To extends string> =
S extends Tpl<infer A, From, infer B>
? Tpl<A, To, ReplaceAll<B, From, To>>
: S;
// split around From, then rejoin with To via template literal types
type X = ReplaceAll<'a-b-c', '-', '_'>; // 'a_b_c'拆分为何重要
拆分是结构化解析的基础。路由按"/"拆分,查询字符串按"&"拆分,CSV 行按","拆分。借助Split,您可以将扁平的字符串类型转换为元组,然后逐个处理其中的元素。
type Segments = Split<"users/42/posts", "/">; // ["users", "42", "posts"]深度限制注意事项
类型级字符串递归受到编译器深度限制的约束。过长的字符串或过多的分隔符可能会超出该限制。对于典型输入(路径、小型格式),它可以顺畅运行。
type Ok = Split<"a/b/c/d/e", "/">; // fine for small strings快速检查
测试您对类型级字符串拆分的理解。
回顾
您已经完全在类型中完成了字符串拆分。
- 模板字面量类型加上
infer可以匹配并捕获字符串片段。 SplitOnce在第一个分隔符处拆分;递归则可以得到完整的Split。- Join、Trim 和 ReplaceAll 都可以由相同的工具组合而成。
下一步:从字符串类型中提取结构化数据。
常见问题解答
「类型级字符串拆分」课时是免费的吗?
是的 — 「类型级字符串拆分」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。
「类型级字符串拆分」这节课中我会学到什么?
在类型系统中将字符串拆分为元组。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 TypeScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「类型级字符串拆分」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 TypeScript Academy 课中编写并运行代码吗?
能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 解析器组合子概念
- 类型级字符串拆分
- 使用模板字面量进行解析
- 小型类型级路由解析器