Replies: 1 comment
-
@tomwidmer Hi,
Manually transforming schemas is possible through json schema introspection, however if the goal is just to derive Read, Create and Update from some entity type, the following is generally more common. import { Type } from '@sinclair/typebox'
// Type to be transformed
export const Customer = Type.Object({
id: Type.String(),
name: Type.String(),
email: Type.String()
})
// Derived transformed types
export const CustomerRead = Type.Pick(Customer, ['id'])
export const CustomerCreate = Type.Omit(Customer, ['id'])
export const CustomerDelete = Type.Index(Customer, ['id'])
export const CustomerUpdate = Type.Composite([
Type.Pick(Customer, ['id']),
Type.Partial(Type.Omit(Customer, ['id']))
]) Which can be generalized to the following (which enforces consistency for the transformation) import { Type, TObject, TString } from '@sinclair/typebox'
// Generic Crud Transforms
export const Read = <T extends TObject<{ id: TString }>>(schema: T) => Type.Pick(schema, ['id'])
export const Create = <T extends TObject<{ id: TString }>>(schema: T) => Type.Omit(schema, ['id'])
export const Delete = <T extends TObject<{ id: TString }>>(schema: T) => Type.Index(schema, ['id'])
export const Update = <T extends TObject<{ id: TString }>>(schema: T) => Type.Composite([
Type.Pick(schema, ['id']),
Type.Partial(Type.Omit(schema, ['id']))
])
// Customer + Ops
export const Customer = Type.Object({
id: Type.String(),
name: Type.String(),
email: Type.String()
})
export const CustomerRead = Read(Customer)
export const CustomerCreate = Create(Customer)
export const CustomerDelete = Delete(Customer)
export const CustomerUpdate = Update(Customer)
// Order + Ops
export const Order = Type.Object({
id: Type.String(),
customerId: Type.String(),
quantity: Type.Number()
})
export const OrderRead = Read(Order)
export const OrderCreate = Create(Order)
export const OrderDelete = Delete(Order)
export const OrderUpdate = Update(Order) Both approaches above would allow you to retain static typing (which is usually a good thing) and is quite common, however, being able to use the above really comes down to your specific usecase.
You will need to implement explicit logic to extract only the schema options. TypeBox doesn't provide any facilities for this. Hope this helps |
Beta Was this translation helpful? Give feedback.
-
I have a 'base' schema, and I need to create a number of somewhat similar, related schemas from this to validate the different variants. I have a base Domain schema (a somewhat nested tree) and I want to derive:
I don't really need type inference for these derived schemas, I just need them for runtime validation and for documentation (e.g. OpenAPI schemas).
This involves transformations that have changes like:
I've got a good generic visitor-type function to handle recursing to sub-schemas, but I'm wondering how to transform the type of a schema while keeping schema options unchanged. When the type is unchanged, I think I just pass the original schema as the schema options:
This should work since the two schemas have the exact same properties, so
transformedParts
will correctly overwrite the changed fields oforiginalSchema
, and we don't end up with any extraneous properties. This will also copy across optionality, etc.However, when the type is changing, so there are different underlying properties in the schema, we have a potential problems:
This doesn't work, since you end up with any extra properties from originalSchemaOfDifferentType (e.g.
pattern
orminimum
) on the new SomeSchema, where they don't apply.Is there any easy way to extract just the 'SchemaOptions' part of a schema, without the type-specific bits, so the extraneous parts are not copied? I think I'm likely on my own here, and I probably need to manually 'omit' all the type specific keys. e.g.
Has anyone else done this kind of thing? Any ideas for something better than the above?
Beta Was this translation helpful? Give feedback.
All reactions