Module

x/typebox/changelog.md

JSON Schema Type Builder with Static Type Resolution for TypeScript
Go to Latest
File

0.17.7

  • Added optional $id argument on Type.Rec().
  • Documentation updates.

0.17.6

  • Added Type.Rec(...) function.

This update introduces the Type.Rec() function for enabling Recursive Types. Please note that due to current inference limitations in TypeScript, TypeBox is unable to infer the type and resolves inner types to any.

This functionality enables for complex self referential schemas to be composed. The following creates a binary expression syntax node with the expression self referential for left and right oprands.

const Operator = Type.Union([
    Type.Literal('+'),
    Type.Literal('-'),
    Type.Literal('/'),
    Type.Literal('*')
])

type Expression = Static<typeof Expression>

// Defines a self referencing type.
const Expression = Type.Rec(Self => Type.Object({
    left:     Type.Union([Self, Type.Number()]), 
    right:    Type.Union([Self, Type.Number()]),
    operator: Operator
}))

function evaluate(expression: Expression): number {
    const left = typeof expression.left  !== 'number' 
        ? evaluate(expression.left as Expression)  // assert as Expression
        : expression.left
    const right = typeof expression.right  !== 'number' 
        ? evaluate(expression.right as Expression) // assert as Expression
        : expression.right
    switch(expression.operator) {
        case '+': return left + right
        case '-': return left - right
        case '*': return left * right
        case '/': return left / right
    }
}

const result = evaluate({
    left: {
        left: 10, 
        operator: '*',
        right: 4, 
    },
    operator: '+',
    right: 2,
}) // -> 42

This functionality is flagged as EXPERIMENTAL and awaits community feedback.

0.17.4

  • Added Type.Box() and Type.Ref() functions.

This update provides the Type.Box() function to enable common related schemas to grouped under a common namespace; typically expressed as a URI. This functionality is primarily geared towards allowing one to define a common set of domain objects that may be shared across application domains running over a network. The Type.Box() is intended to be an analog to XML xmlns namespacing.

The Type.Ref() function is limited to referencing from boxes only. The following is an example.

// Domain objects for the fruit service.
const Fruit = Type.Box('https://fruit.domain.com', {
    Apple:  Type.Object({ ... }),
    Orange: Type.Object({ ... }),
})

// An order referencing types of the fruit service.
const Order = Type.Object({
    id:       Type.String(),
    quantity: Type.Number(),
    item:     Type.Union([
        Type.Ref(Fruit, 'Apple'),
        Type.Ref(Fruit, 'Orange')
    ])
})

Note: As of this release, the Type.Omit(), Type.Pick(), Type.Partial(), Type.Readonly() and Type.Intersect() functions do not work with Reference Types. This may change in later revisions.

For validation using Ajv, its possible to apply the Box directly as a schema.

ajv.addSchema(Fruit) // makes all boxed types known to Ajv

This functionality is flagged as EXPERIMENTAL and awaits community feedback.

0.17.1

  • Remove default additionalProperties: false constraint from all object schemas.

This update removes the additionalProperties: false constraint on all object schemas. This constraint was introduced on 0.16.x but has resulted in significant downstream problems composing schemas whose types intersect. This is due to a JSON schema design principle where constraints should only be added (never removed), and that intersection types may require removal of the additionalProperties constraint in some cases, this had resulted in some ambiguity with respect to how TypeBox should handle such intersections.

This update can also be seen as a precursor towards TypeBox potentially leveraging unevaluatedProperties for type intersection in future releases. Implementors should take note that in order to constrain the schema to known properties, one should apply the additionalProperties: false as the second argument to Type.Object({...}).

const T = Type.Object({
    a: Type.String(),
    b: Type.Number()
}, { 
    additionalProperties: false 
})