Libraries
    Preparing search index...

    Function defineExtension

    • Defines an extension targeting one or more schema builder types.

      Each extension is a plain object keyed by builder type name ("string", "number", "date", …) whose values are method implementations. Methods receive this bound to the builder instance and must return a builder to support fluent chaining.

      Extension methods do not have to call this.withExtension(). The system wraps each method and automatically attaches withExtension(methodName, args) to the returned builder when the key is not already present. This eliminates the most common source of duplication in extension code.

      • Zero-arg methods → metadata value is true
      • Single-arg methods → metadata value is the argument itself
      • Multi-arg methods → metadata value is the arguments array

      If you need custom metadata (e.g. a different key, a transformed value, or a structured object), call this.withExtension(key, value) explicitly inside the method — the auto-infer logic detects the existing key and skips automatic attachment.

      defineExtension validates the configuration eagerly:

      • Unknown builder type names throw immediately.
      • RESERVED_METHODS | Reserved method names (e.g. validate, introspect) cannot be overridden.
      • Non-function values in the method record are rejected.

      Type Parameters

      Parameters

      • config: T

        An ExtensionConfig object mapping builder type names to method records.

      Returns ExtensionDescriptor<T>

      A branded ExtensionDescriptor ready to pass to withExtensions.

      const slugExt = defineExtension({
      string: {
      slug(this: StringSchemaBuilder) {
      return this.addValidator((val) => {
      const valid = /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(val);
      return { valid, errors: valid ? [] : [{ message: 'invalid slug' }] };
      });
      }
      }
      });

      // Usage:
      const s = withExtensions(slugExt);
      const schema = s.string().slug();
      schema.introspect().extensions.slug; // true
      const currencyExt = defineExtension({
      number: {
      currency(this: NumberSchemaBuilder, opts?: { maxDecimals?: number }) {
      const maxDec = opts?.maxDecimals ?? 2;
      return this.withExtension('currency', { maxDecimals: maxDec })
      .min(0)
      .addValidator((val) => {
      const decimals = (String(val).split('.')[1] ?? '').length;
      const valid = decimals <= maxDec;
      return { valid, errors: valid ? [] : [{ message: `max ${maxDec} decimals` }] };
      });
      }
      }
      });
      const myExt = defineExtension({
      string: {
      email(this: StringSchemaBuilder) { return this.addValidator(...); }
      },
      number: {
      port(this: NumberSchemaBuilder) { return this.isInteger().min(1).max(65535); }
      }
      });

      If a builder type name is unknown.

      If a method name is reserved.

      If a method value is not a function.