我想在typescript的型別級別實作json序列化和反序列化。
我在github上找到了反序列化的實作。
如何實作序列化?
uj5u.com熱心網友回復:
我不知道你所說的“型別級序列化”是什么意思,但你可以將它們包裝在型別檢查函式中。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;
uj5u.com熱心網友回復:
我自己實作了:
// 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.
但這對我來說已經足夠了,任何優化方案請在評論中提出。
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/367035.html
