【发布时间】:2022-01-04 08:52:38
【问题描述】:
【问题讨论】:
-
也许您需要的是
class-validator和class-transformer包。
标签: json typescript serialization
【问题讨论】:
class-validator 和 class-transformer 包。
标签: json typescript serialization
我自己实现的:
// 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.
但这对我来说已经足够了,任何优化方案请在cmets中提出。
【讨论】:
我不知道您所说的“类型级序列化”是什么意思,但您可以将它们包装在类型检查函数中。 stringify 可以在类型检查函数上正常工作,因为 TypeScript 可以对输入进行类型检查:
function serialize(data: SomeInterface): string {
return JSON.stringify(data);
}
反序列化更加棘手,因为输入 string 可能包含任何内容。我认为您无法解决此编译时问题。因此,在这种情况下,如果您需要更多保证,则需要进行运行时验证:
function deserialize(input: string): SomeInterface {
const data = JSON.parse(input);
// Do some validation
return data;
}
如果您绝对确定输入字符串符合接口,那么您可以进行转换:
const data = JSON.parse(input) as SomeInterface;
【讨论】:
x1、x2、x3的类型。 “类型级别”是指对类型进行编程,类似于函数调用,只是参数都是类型而不是值,调用的结果也是类型而不是值。通过一个或多个类型生成一个新类型。这是类型级别的编程。对我来说,这可以帮助我更好地描述程序的类型约束。