What is the proper way to parse decoded data? #1089
-
I use Typebox in backend and some schemas have type transformation (mostly for dates, where encoded value is By readiing some issues in this repo, source code and after a couple trials and errors, i found result which seems works as i want. I'd like to hear your feedback on this function, and ask for any potential issues, or if there is better/proper way to do this? export function parseDecoded<T extends TSchema>(
schema: T,
data: unknown,
): StaticDecode<T> {
const clonedData = Value.Clone(data);
const defaultData = Value.Default(schema, clonedData);
const cleanedData = Value.Clean(schema, defaultData);
const encodedData = Value.Encode(schema, cleanedData);
const decodedData = Value.Decode(schema, encodedData);
return decodedData;
} P.S. I've tried to use both Thanks in advance @sinclairzx81! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
@anotheri Hi,
The example code you provided is perfectly fine for processing a value. TypeBox isn't very opinionated with respect to the functions used, or the order in which they are used. However, the Parse function does provide a library nominated "ideal" way to call these functions (but it is the kitchen sink) https://github.com/sinclairzx81/typebox/blob/master/src/value/parse/parse.ts#L43C1-L57C2
It is possible to setup Transform pipelines that run a sequence of Transforms. This would for example, allow you to transform from import { Type, FormatRegistry } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'
// ------------------------------------------------------------------
// Set: date-time format
//
// TypeBox does not include any string formats by default. You will
// need to specify what the 'date-time' format is.
//
// ------------------------------------------------------------------
const iso8601Regex = /^(\d{4})-(\d{2})-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.\d{1,3})?)?([+-](\d{2}):?(\d{2})|Z)?)?$/;
FormatRegistry.Set('date-time', (value) => iso8601Regex.test(value))
// ------------------------------------------------------------------
// Transform: StringToDate
//
// This Transform will convert a iso8601 Date string into a Date
// object. Typically you would use this to receive string encoded
// dates on your server.
// ------------------------------------------------------------------
const StringToDate = Type.Transform(Type.String({ format: 'date-time' }))
.Decode(value => new Date(value))
.Encode(value => value.toISOString())
// ------------------------------------------------------------------
// Transform: StringToDateToSuperDate
//
// This Transform converts a StringToDate (above) into a SuperDate
// structure. This kind of Transform would be uncommon, but it is
// possible to pipeline Transform > Transform in some cases.
//
// ------------------------------------------------------------------
const StringToDateToSuperDate = Type.Transform(StringToDate)
.Decode(value => ({ super: value }))
.Encode(value => value.super)
// ------------------------------------------------------------------
// Usage
//
// The following creates a type T with embedded StringToDateToSuperDate.
// We use the Parse function which will invoke the string format, two
// transforms and return a matching type T.
//
// ------------------------------------------------------------------
const T = Type.Object({
date: StringToDateToSuperDate
})
const R = Value.Parse(T, { // const R: {
date: '2024-11-20T14:54:56.334Z' // date: {
}) // super: Date;
// };
// }
console.log(R) // {
// date: {
// super: 2024-11-20T14:54:56.334Z
// }
// }
// ... Encode will re-encode to the original value
const E = Value.Encode(T, R) // { date: '2024-11-20T14:54:56.334Z' }
Note the above would be quite uncommon. Multiple levels of Transforms can lead to quite a bit of complexity. Usually if you need to perform a Transform, you would keep that one level deep (StringToDate), but TypeBox will let you stack as many transforms as required. So, hopefully the above is helpful. Give the above a test run and see how you go. If you have any other questions, feel free to ping on this thread. Cheers |
Beta Was this translation helpful? Give feedback.
@anotheri Hi,
The example code you provided is perfectly fine for processing a value. TypeBox isn't very opinionated with respect to the functions used, or the order in which they are used. However, the Parse function does provide a library nominated "ideal" way to call these functions (but it is the kitchen sink)
https://github.com/sinclairzx81/typebox/blob/master/src/value/parse/parse.ts#L43C1-L57C2