Closed eropple closed 1 year ago
@eropple Hi!
You can use functions to simulate generics in TypeBox. The common pattern is to pass a generic argument constrained to some type of TSchema
(so <T extends TSchema>
is very common). For example....
// -----------------------------------------------------------------
// TypeScript Generics
// -----------------------------------------------------------------
export type Vector<T> = { x: T, y: T, z: T }
export type BooleanVector = Vector<boolean>
export type NumberVector = Vector<number>
// -----------------------------------------------------------------
// TypeBox Generics
// -----------------------------------------------------------------
export const Vector = <T extends TSchema>(t: T) => Type.Object({ x: t, y: t, z: t })
export const BooleanVector = Vector(Type.Boolean())
export const NumberVector = Vector(Type.Boolean())
So from this, you can implement a Base and Derived in the following way. Note that for Intersect types, you will need to constrain to TObject
.
import { Type, Static, TObject } from '@sinclair/typebox'
export const Base = <T extends TObject>(derived: T) => Type.Intersect([
Type.Object({
requiredField: Type.String(),
}),
derived
])
export type BaseDefault = Static<typeof BaseDefault> // optional: if you need to instance the base
export const BaseDefault = Base(Type.Object({})) // without any derived properties
export type Derived = Static<typeof Derived>
export const Derived = Base(Type.Object({
derivedField: Type.String(),
}))
Hope this helps! S
Thanks for the quick reply! I think I've cracked it; my confusion was around the relationship between Base
, typeof Base
, and Static<typeof Base>
. I was having trouble expressing how to go T extends (a TObject shaped like Base)
and figured out that that's T extends typeof Base
, which cracked it open for me.
Hey there! Thanks for typebox, this library is awesome.
I've been digging through prior issues, and I feel like this has to be answered somewhere, but I'm at a loss for it. I'd appreciate some guidance with this problem. I've got a base type, defined in TypeBox, e.g.
I then extend the type with
Type.Intersect
:What I'm trying to do from here is genericize a function (in my case, JWT validation, but it extends to a lot of stuff) that accepts a schema that must implement
Base
, while returningStatic<T extends Base>
out of the function (that is, if passedDerived
, it must return aDerived
.I assume this is a known pattern; is there an example of it somewhere? I'm just looking for a handhold from which to start, so if there's something useful to read, I'm very happy to. Thanks!