TypeScript中如何获取JSON序列化反序列化后的对象类型?
实现
JSONTypeOf<T>泛型以获取JSON序列化后的对象类型 要模拟JSON.stringify()转JSON再JSON.parse()解析后的对象类型,我们需要一个泛型来过滤掉不可序列化的属性(比如函数、Symbol),同时转换特殊类型(比如Date会变成ISO字符串)。以下是具体实现方案:
核心泛型实现
type JSONTypeOf<T> = // Date对象会被序列化为ISO字符串 T extends Date ? string : // BigInt无法被JSON序列化,直接标记为never(序列化会报错) T extends bigint ? never : // 数组中的函数、Symbol、undefined会被转为null T extends Function | symbol | undefined ? null : // 处理对象和数组的嵌套结构 T extends object ? T extends Array<infer U> ? Array<JSONTypeOf<U>> : // 过滤对象中不可序列化的属性键,递归处理剩余属性值 { [K in keyof T as T[K] extends Function | symbol | undefined ? never : K]: JSONTypeOf<T[K]> } : // 基础类型(string/number/boolean/null)保持原样 T;
逻辑说明
- 特殊类型处理:
Date:JSON序列化后会变成ISO格式的字符串,所以直接映射为string类型。bigint:JSON无法序列化BigInt,序列化时会抛出错误,因此标记为never。
- 不可序列化值处理:
- 函数、Symbol、
undefined在数组中会被JSON.stringify()转为null,所以映射为null类型。 - 在对象中,这些属性会被直接忽略,因此通过映射类型过滤掉对应的键。
- 函数、Symbol、
- 嵌套结构递归:
- 数组:递归处理每个元素的类型。
- 普通对象:过滤掉不可序列化属性后,递归处理剩余属性的值类型。
示例验证
用你提供的squirrel对象测试:
const squirrel = { name: "Töski", nuts: 392, consumeNut() { this.nuts -= 1; }, birthDate: new Date(), favoriteSymbol: Symbol("nut"), maybeUndefined: undefined }; // 获取序列化后的类型 type AfterJSONSquirrel = JSONTypeOf<typeof squirrel>;
最终AfterJSONSquirrel的类型为:
{ name: string; nuts: number; birthDate: string; }
再测试嵌套数组的情况:
const testArr = [() => {}, undefined, Symbol("test"), new Date(), 123]; type AfterJSONArr = JSONTypeOf<typeof testArr>; // 类型为:(null | string | number)[]
内容的提问来源于stack exchange,提问作者Evan Summers
相关产品推荐
相关产品推荐

