如何在TypeScript类型层面实现JSON序列化与反序列化
TypeScript 类型层面JSON序列化实现方案
核心思路
利用TypeScript内置的条件类型、递归类型、模板字面量类型,逐分支匹配不同的JSON合法类型,递归生成对应的JSON字符串字面量类型,完整对齐原生JSON.stringify的核心行为。
基础实现代码
// 特殊字符转义映射 type EscapeMap = { '"': '\\"' '\\': '\\\\' '\n': '\\n' '\r': '\\r' '\t': '\\t' '\b': '\\b' '\f': '\\f' } // 单个字符转义 type EscapeChar<T extends string> = T extends keyof EscapeMap ? EscapeMap[T] : T // 字符串全量转义 type EscapeString<T extends string> = T extends `${infer First}${infer Rest}` ? `${EscapeChar<First>}${EscapeString<Rest>}` : '' // 字符串联合类型拼接辅助 type Join<Items extends string, Separator extends string> = Items extends `${infer First}${infer Rest}` ? Rest extends '' ? First : `${First}${Separator}${Join<Rest, Separator>}` : Items extends string[] ? Items extends [infer First extends string, ...infer Rest extends string[]] ? `${First}${Rest extends [] ? '' : `${Separator}${Join<Rest, Separator>}`}` : '' : '' // 对象序列化辅助 type SerializeObject<T extends object> = { [K in keyof T as T[K] extends undefined ? never : K]: K extends string ? `"${EscapeString<K>}":${SerializeJSON<T[K]>}` : never } extends infer FieldMap ? FieldMap[keyof FieldMap] extends infer Fields extends string ? Fields extends '' ? '{}' : `{${Join<Fields, ','>}}` : '{}' : '{}' // 主序列化类型 type SerializeJSON<T> = // 处理null T extends null ? 'null' : // 处理布尔值 T extends boolean ? `${T}` : // 处理数字,NaN/Infinity等非合法JSON数字统一返回null T extends number ? number extends T ? string : `${T}` extends `${number}` ? `${T}` : 'null' : // 处理字符串 T extends string ? `"${EscapeString<T>}"` : // 处理数组 T extends [infer First, ...infer Rest] ? `[${SerializeJSON<First>}${Rest extends [] ? '' : `,${SerializeJSON<Rest>}`}]` : T extends Array<infer Elem> ? `[${SerializeJSON<Elem>}]` : // 处理对象 T extends object ? SerializeObject<T> : // 处理undefined/函数/Symbol等JSON不支持类型,序列化时自动忽略 undefined
效果测试
// 测试类型 type TestInput = { userId: 10086 userName: "Zhang \"San\"" isVip: true expired: null tags: ["frontend", "typescript", 2024] profile: { city: "Shanghai\nPudong" level: 5 } } // 序列化结果类型 type Output = SerializeJSON<TestInput> // 推导结果为: // '{"userId":10086,"userName":"Zhang \\"San\\"","isVip":true,"expired":null,"tags":["frontend","typescript",2024],"profile":{"city":"Shanghai\\nPudong","level":5}}'
已知限制
- 受TypeScript递归深度阈值限制,无法处理层级超过50的嵌套类型
- 超出安全整数范围的大数字转换为模板字面量时会出现精度丢失
- 无法完全对齐原生
JSON.stringify的所有边缘行为(比如BigInt序列化报错、循环引用处理等) - 泛型类型、索引签名类型的序列化结果会做降级处理,无法得到精确的字面量结果
内容的提问来源于stack exchange,提问作者hby
相关产品推荐
相关产品推荐

