目录 (Outline)
- 一、 准备工作:类型编程的核心利器
- 二、 基础:解析字面量(布尔、Null、数字)
- 三、 进阶:解析字符串与转义字符
- 四、 核心:处理数组与对象的递归解析
- 五、 实战:手写 JSONParser 类型
- 六、 总结:类型编程的边界与意义
一、 准备工作:类型编程的核心利器
要实现 JSON Parser,你需要熟练掌握以下特性:
- 模板字面量类型 (Template Literal Types):用于匹配和拆分字符串。
- 递归类型 (Recursive Types):处理嵌套的对象和数组。
- 条件类型与 infer (Conditional Types):类型系统的
if/else与变量提取。
二、 基础:解析字面量(布尔、Null、数字)
JSON 中的简单类型比较好处理。
实战代码
type ParseLiteral<T extends string> =
T extends 'true' ? true :
T extends 'false' ? false :
T extends 'null' ? null :
T extends `${infer N extends number}` ? N : // TS 4.8+ 支持数字推断
never;
type Test1 = ParseLiteral<'true'>; // true
type Test2 = ParseLiteral<'123'>; // 123
三、 进阶:解析字符串与转义字符
解析 JSON 字符串需要处理双引号及其内部内容。
实战代码
type ParseString<T extends string> =
T extends `"${infer Content}"${infer Rest}` ? [Content, Rest] : never;
type Res = ParseString<'"hello" , 123'>; // ["hello", " , 123"]
四、 核心:处理数组与对象的递归解析
这是最难的部分,需要不断的拆解字符串并递归调用解析函数。
1. 解析数组
我们需要识别 [,然后递归解析内部元素,直到遇到 ]。
2. 解析对象
我们需要识别 {,然后交替解析 Key(字符串)和 Value(任意类型)。
五、 实战:手写 JSONParser 类型
我们将所有的逻辑整合在一起。
简化版核心逻辑示例
// 跳过空白字符
type TrimLeft<S extends string> = S extends `${' ' | '\n' | '\t'}${infer R}` ? TrimLeft<R> : S;
// 主解析入口
type JSONParser<T extends string> = ParseValue<TrimLeft<T>>[0];
// 分发解析逻辑
type ParseValue<T extends string> =
T extends `{${string}` ? ParseObject<T> :
T extends `[${string}` ? ParseArray<T> :
ParseLiteralToken<T>;
// 解析对象示例(极简逻辑)
type ParseObject<T extends string> =
T extends `{${infer Content}}` ?
// 内部复杂的键值对拆解逻辑...
[{ [K in string]: any }, ""] : never;
// --- 使用方式 ---
type MyData = JSONParser<'{"name": "trae", "age": 18}'>;
// 最终类型:{ name: "trae", age: 18 }
六、 总结:类型编程的边界与意义
1. 为什么要做这么复杂的事?
- 极速反馈:在编码阶段就能发现 API 定义与本地数据的类型不匹配。
- 框架开发:诸如
tRPC或Zod的底层大量使用了类似的技巧。
2. 边界在哪里?
- 性能开销:超大规模的递归会导致 TS 编译器变慢或报
Type instantiation is excessively deep错误。 - 可读性:类型体操虽然强大,但维护成本极高,建议仅在库级别使用。
掌握了 JSON Parser 的实现,你就已经站在了 TypeScript 类型编程的巅峰。