# Schema.Advanced

The Schema submodule enables user-defined JSON Schema layouts and provides type inference beyond the types available through the Type.* compositors. The following example shows a hypothetical GraphicsModule containing several cross-dependent types that utilize the $defs keyword for reusable schema definitions. The implementation provides a custom import that merges the definitions with a $ref entry point. The type definitions and their corresponding functions are structured symmetrically.

> ⚠️ Native JSON Schema inference and validation is an evolving feature of the TypeBox library. Due to the highly flexible nature of schema layouts, TypeBox cannot provide a simplified interface for every possible layout. Consequently, leveraging native JSON Schema inference may require a moderate level of familiarity with type-level programming concepts.

GraphicsModule Reference Link

    import Type from 'typebox'

    // ------------------------------------------------------------------------------
    // TImport<Module, Ref>
    //
    // Import definitions types from { $defs } schematic layouts.
    // ------------------------------------------------------------------------------
    export type TImport<
      Module extends { $defs: Type.TProperties },
      Ref extends string = Extract<keyof Module['$defs'], string>
    > = (
      Module & { $ref: `#/$defs/${Ref}` }
    )
    export function Import<
      Module extends { $defs: Type.TProperties },
      Ref extends string = Extract<keyof Module['$defs'], string>
    >(module: Module, ref: Ref): TImport<Module, Ref> {
      return { ...module, $ref: `#/$defs/${ref}` } as never
    }

    // ------------------------------------------------------------------------------
    // Reference: GraphicsModule
    //
    // Layout for cross-dependent type definitions
    // ------------------------------------------------------------------------------
    export const GraphicsModule = {
      $defs: {
        Vector2: Type.Object({
          x: Type.Number(),
          y: Type.Number()
        }),
        Vector3: Type.Object({
          x: Type.Number(),
          y: Type.Number(),
          z: Type.Number()
        }),
        Vertex: Type.Object({
          position: Type.Ref('#/$defs/Vector3'),
          normal: Type.Ref('#/$defs/Vector3'),
          texcoord: Type.Ref('#/$defs/Vector2'),
        }),
        Geometry: Type.Object({
          vertices: Type.Array(Type.Ref('#/$defs/Vertex')),
          indices: Type.Array(Type.Integer())
        }),
        Material: Type.Object({
          ambient: Type.Ref('#/$defs/Vector3'),
          diffuse: Type.Ref('#/$defs/Vector3'),
          specular: Type.Ref('#/$defs/Vector3'),
        }),
        Mesh: Type.Object({
          geometry: Type.Ref('#/$defs/Geometry'),
          material: Type.Ref('#/$defs/Material'),
        })
      }
    } as const

    // ------------------------------------------------------------------------------
    // Schematics and Inference
    //
    // We can derive schematics and inference in the following way
    // ------------------------------------------------------------------------------

    export type Vector2 = Type.Static<typeof Vector2>
    export type Vector3 = Type.Static<typeof Vector3>
    export type Vertex = Type.Static<typeof Vertex>
    export type Geometry = Type.Static<typeof Geometry>
    export type Material = Type.Static<typeof Material>
    export type Mesh = Type.Static<typeof Mesh>

    export const Vector2 = Import(GraphicsModule, 'Vector2')
    export const Vector3 = Import(GraphicsModule, 'Vector3')
    export const Vertex = Import(GraphicsModule, 'Vertex')
    export const Geometry = Import(GraphicsModule, 'Geometry')
    export const Material = Import(GraphicsModule, 'Material')
    export const Mesh = Import(GraphicsModule, 'Mesh')

    // ------------------------------------------------------------------------------
    // Validation
    // ------------------------------------------------------------------------------
    import { Parse } from 'typebox/schema'

    const mesh = Parse(Mesh, {
      material: {
        ambient: { x: 1, y: 2, z: 3 },
        diffuse: { x: 1, y: 2, z: 3 },
        specular: { x: 1, y: 2, z: 3 },
      },
      geometry: {
        indices: [0],
        vertices: [{
          position: { x: 1, y: 2, z: 3 },
          normal: { x: 1, y: 2, z: 3 },
          texcoord: { x: 1, y: 2 },
        }]
      }
    })