我想在typescript的类型级别实现json序列化和非序列化。我在github上找到了一个实现。如何实现序列化?
vmjh9lq91#
我自己实现的:
// https://github.com/type-challenges/type-challenges/issues/2835 type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer U) => any ? U : never type LastUnion<T> = UnionToIntersection<T extends any ? (x: T) => any : never> extends (x: infer L) => any ? L : never export type UnionToTuple<T, Last = LastUnion<T>> = [T] extends [never] ? [] : [...UnionToTuple<Exclude<T, Last>>, Last] type obj2json<keys, T> = keys extends [] ? '' : keys extends [infer a] ? a extends string ? a extends keyof T ? `"${a}":${stringify<T[a]>}` : never : never : keys extends [infer a, ...infer as] ? a extends string ? a extends keyof T ? `"${a}":${stringify<T[a]>},${obj2json<as, T>}` : never : never : never type arr2json<items> = items extends [] ? '' : items extends [infer a] ? `${stringify<a>}` : items extends [infer a, ...infer as] ? `${stringify<a>},${arr2json<as>}` : never type stringify<T> = T extends object ? T extends Array<unknown> ? `[${arr2json<T>}]` : UnionToTuple<keyof T> extends infer keys ? `{${obj2json<keys, T>}}` : never : T extends string ? `"${T}"` : T extends number ? `${T}` : T extends boolean ? `${T}` : never type x1 = stringify<{ a: '1'; b: 2; c: { a: 1 } }> type x2 = stringify<{ a: [1, 2, 3] }> type x3 = stringify<{ a: [1, 2, { a: 1; b: 2; c: [1, true] }] }>
这是一个没有递归优化的粗略实现。当json级别太多时,可能会出现错误:Type instantiation is excessively deep and possibly infinite.但这对我来说已经足够了,任何优化方案请在评论中提出建议。操场
Type instantiation is excessively deep and possibly infinite.
kqhtkvqz2#
我不知道你说的“类型级序列化”是什么意思,但是你可以把这些封装在类型检查函数中。stringify在类型检查的函数上工作得很好,因为TypeScript可以对输入进行类型检查:
stringify
function serialize(data: SomeInterface): string { return JSON.stringify(data); }
示例化更棘手,因为输入string可能包含任何内容。我不认为你能在编译时解决这个问题。所以,在这种情况下,如果你需要更多的保证,你需要做运行时验证:
string
function deserialize(input: string): SomeInterface { const data = JSON.parse(input); // Do some validation return data; }
如果你绝对确定输入字符串符合接口,那么你可以直接强制转换:
const data = JSON.parse(input) as SomeInterface;
ubby3x7f3#
不确定理解什么是“在类型级别”,但如果它意味着用类示例代替值(例如Date示例或您自己的类示例),那么您可能会对@badcafe/jsonizer感兴趣:https://badcafe.github.io/jsonizer/#/
Date
@badcafe/jsonizer
3条答案
按热度按时间vmjh9lq91#
我自己实现的:
这是一个没有递归优化的粗略实现。当json级别太多时,可能会出现错误:
Type instantiation is excessively deep and possibly infinite.
但这对我来说已经足够了,任何优化方案请在评论中提出建议。
操场
kqhtkvqz2#
我不知道你说的“类型级序列化”是什么意思,但是你可以把这些封装在类型检查函数中。
stringify
在类型检查的函数上工作得很好,因为TypeScript可以对输入进行类型检查:示例化更棘手,因为输入
string
可能包含任何内容。我不认为你能在编译时解决这个问题。所以,在这种情况下,如果你需要更多的保证,你需要做运行时验证:如果你绝对确定输入字符串符合接口,那么你可以直接强制转换:
ubby3x7f3#
不确定理解什么是“在类型级别”,但如果它意味着用类示例代替值(例如
Date
示例或您自己的类示例),那么您可能会对@badcafe/jsonizer
感兴趣:https://badcafe.github.io/jsonizer/#/