UNPKG

superstruct

Version:

A simple and composable way to validate data in JavaScript (and TypeScript).

1,236 lines (1,235 loc) • 28.8 kB
/** * A `StructFailure` represents a single specific failure in validation. */ type Failure = { value: any; key: any; type: string; refinement: string | undefined; message: string; branch: Array<any>; path: Array<any>; }; /** * `StructError` objects are thrown (or returned) when validation fails. * * Validation logic is design to exit early for maximum performance. The error * represents the first error encountered during validation. For more detail, * the `error.failures` property is a generator function that can be run to * continue validation and receive all the failures in the data. */ declare class StructError extends TypeError { value: any; key: any; type: string; refinement: string | undefined; path: Array<any>; branch: Array<any>; failures: () => Array<Failure>; [x: string]: any; constructor(failure: Failure, failures: () => Generator<Failure>); } /** * Check if a type is a tuple. */ type IsTuple<T> = T extends [ any ] ? T : T extends [ any, any ] ? T : T extends [ any, any, any ] ? T : T extends [ any, any, any, any ] ? T : T extends [ any, any, any, any, any ] ? T : never; /** * Check if a type is a record type. */ type IsRecord<T> = T extends object ? string extends keyof T ? T : never : never; /** * Check if a type is a generic string type. */ type IsGenericString<T> = T extends string ? string extends T ? T : never : never; /** * Normalize properties of a type that allow `undefined` to make them optional. */ type Optionalize<S extends object> = OmitBy<S, undefined> & Partial<PickBy<S, undefined>>; /** * Omit properties from a type that extend from a specific type. */ type OmitBy<T, V> = Omit<T, { [K in keyof T]: V extends Extract<T[K], V> ? K : never; }[keyof T]>; /** * Pick properties from a type that extend from a specific type. */ type PickBy<T, V> = Pick<T, { [K in keyof T]: V extends Extract<T[K], V> ? K : never; }[keyof T]>; /** * Simplifies a type definition to its most basic representation. */ type Simplify<T> = T extends any[] | Date ? T : { [K in keyof T]: T[K]; } & {}; /** * Assign properties from one type to another, overwriting existing. */ type Assign<T, U> = Simplify<U & Omit<T, keyof U>>; /** * A schema for object structs. */ type ObjectSchema = Record<string, Struct<any, any>>; /** * Infer a type from an object struct schema. */ type ObjectType<S extends ObjectSchema> = Simplify<Optionalize<{ [K in keyof S]: Infer<S[K]>; }>>; /** * Transform an object schema type to represent a partial. */ type PartialObjectSchema<S extends ObjectSchema> = { [K in keyof S]: Struct<Infer<S[K]> | undefined>; }; /** * A schema for any type of struct. */ type StructSchema<T> = [ T ] extends [ string ] ? [ T ] extends [ IsGenericString<T> ] ? null : EnumSchema<T> : T extends number | boolean | bigint | symbol | undefined | null | Function | Date | Error | RegExp ? null : T extends Map<any, any> ? null : T extends WeakMap<any, any> ? null : T extends Set<any> ? null : T extends WeakSet<any> ? null : T extends Array<infer E> ? T extends IsTuple<T> ? null : Struct<E> : T extends Promise<any> ? null : T extends object ? T extends IsRecord<T> ? null : { [K in keyof T]: Describe<T[K]>; } : null; /** * A schema for enum structs. */ type EnumSchema<T extends string> = { [K in T]: K; }; /** * A schema for tuple structs. */ type TupleSchema<T> = { [K in keyof T]: Struct<T[K]>; }; /** * `Struct` objects encapsulate the validation logic for a specific type of * values. Once constructed, you use the `assert`, `is` or `validate` helpers to * validate unknown input data against the struct. */ declare class Struct<T = unknown, S = unknown> { readonly TYPE: T; type: string; schema: S; coercer: (value: unknown, context: Context) => unknown; validator: (value: unknown, context: Context) => Iterable<Failure>; refiner: (value: T, context: Context) => Iterable<Failure>; entries: (value: unknown, context: Context) => Iterable<[ string | number, unknown, Struct<any> | Struct<never> ]>; constructor(props: { type: string; schema: S; coercer?: Coercer; validator?: Validator; refiner?: Refiner<T>; entries?: Struct<T, S>["entries"]; }); /** * Assert that a value passes the struct's validation, throwing if it doesn't. */ assert(value: unknown): asserts value is T; /** * Create a value with the struct's coercion logic, then validate it. */ create(value: unknown): T; /** * Check if a value passes the struct's validation. */ is(value: unknown): value is T; /** * Mask a value, coercing and validating it, but returning only the subset of * properties defined by the struct's schema. */ mask(value: unknown): T; /** * Validate a value with the struct's validation logic, returning a tuple * representing the result. * * You may optionally pass `true` for the `withCoercion` argument to coerce * the value before attempting to validate it. If you do, the result will * contain the coerced result when successful. */ validate(value: unknown, options?: { coerce?: boolean; }): [ StructError, undefined ] | [ undefined, T ]; } /** * Assert that a value passes a struct, throwing if it doesn't. */ declare function assert<T, S>(value: unknown, struct: Struct<T, S>): asserts value is T; /** * Create a value with the coercion logic of struct and validate it. */ declare function create<T, S>(value: unknown, struct: Struct<T, S>): T; /** * Mask a value, returning only the subset of properties defined by a struct. */ declare function mask<T, S>(value: unknown, struct: Struct<T, S>): T; /** * Check if a value passes a struct. */ declare function is<T, S>(value: unknown, struct: Struct<T, S>): value is T; /** * Validate a value against a struct, returning an error if invalid, or the * value (with potential coercion) if valid. */ declare function validate<T, S>(value: unknown, struct: Struct<T, S>, options?: { coerce?: boolean; mask?: boolean; }): [ StructError, undefined ] | [ undefined, T ]; /** * A `Context` contains information about the current location of the * validation inside the initial input value. */ type Context = { branch: Array<any>; path: Array<any>; }; /** * A type utility to extract the type from a `Struct` class. */ type Infer<T extends Struct<any, any>> = T["TYPE"]; /** * A type utility to describe that a struct represents a TypeScript type. */ type Describe<T> = Struct<T, StructSchema<T>>; /** * A `Result` is returned from validation functions. */ type Result = boolean | string | Partial<Failure> | Iterable<boolean | string | Partial<Failure>>; /** * A `Coercer` takes an unknown value and optionally coerces it. */ type Coercer<T = unknown> = (value: T, context: Context) => unknown; /** * A `Validator` takes an unknown value and validates it. */ type Validator = (value: unknown, context: Context) => Result; /** * A `Refiner` takes a value of a known type and validates it against a further * constraint. */ type Refiner<T> = (value: T, context: Context) => Result; /** * Augment a `Struct` to add an additional coercion step to its input. * * This allows you to transform input data before validating it, to increase the * likelihood that it passes validation—for example for default values, parsing * different formats, etc. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ declare function coerce<T, S, C>(struct: Struct<T, S>, condition: Struct<C, any>, coercer: Coercer<C>): Struct<T, S>; /** * Augment a struct to replace `undefined` values with a default. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ declare function defaulted<T, S>(struct: Struct<T, S>, fallback: any, options?: { strict?: boolean; }): Struct<T, S>; /** * Augment a struct to trim string inputs. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ declare function trimmed<T, S>(struct: Struct<T, S>): Struct<T, S>; /** * Ensure that a string, array, map, or set is empty. */ declare function empty<T extends string | any[] | Map<any, any> | Set<any>, S extends any>(struct: Struct<T, S>): Struct<T, S>; /** * Ensure that a number or date is below a threshold. */ declare function max<T extends number | Date, S extends any>(struct: Struct<T, S>, threshold: T, options?: { exclusive?: boolean; }): Struct<T, S>; /** * Ensure that a number or date is above a threshold. */ declare function min<T extends number | Date, S extends any>(struct: Struct<T, S>, threshold: T, options?: { exclusive?: boolean; }): Struct<T, S>; /** * Ensure that a string matches a regular expression. */ declare function pattern<T extends string, S extends any>(struct: Struct<T, S>, regexp: RegExp): Struct<T, S>; /** * Ensure that a string, array, number, date, map, or set has a size (or length, or time) between `min` and `max`. */ declare function size<T extends string | number | Date | any[] | Map<any, any> | Set<any>, S extends any>(struct: Struct<T, S>, min: number, max?: number): Struct<T, S>; /** * Augment a `Struct` to add an additional refinement to the validation. * * The refiner function is guaranteed to receive a value of the struct's type, * because the struct's existing validation will already have passed. This * allows you to layer additional validation on top of existing structs. */ declare function refine<T, S>(struct: Struct<T, S>, name: string, refiner: Refiner<T>): Struct<T, S>; /** * Ensure that any value passes validation. */ declare function any(): Struct<any, null>; /** * Ensure that a value is an array and that its elements are of a specific type. * * Note: If you omit the element struct, the arrays elements will not be * iterated at all. This can be helpful for cases where performance is critical, * and it is preferred to using `array(any())`. */ declare function array<T extends Struct<any>>(Element: T): Struct<Infer<T>[], T>; declare function array(): Struct<unknown[], undefined>; /** * Ensure that a value is a boolean. */ declare function boolean(): Struct<boolean, null>; /** * Ensure that a value is a valid `Date`. * * Note: this also ensures that the value is *not* an invalid `Date` object, * which can occur when parsing a date fails but still returns a `Date`. */ declare function date(): Struct<Date, null>; /** * Ensure that a value is one of a set of potential values. * * Note: after creating the struct, you can access the definition of the * potential values as `struct.schema`. */ declare function enums<T extends number>(values: readonly T[]): Struct<T, { [K in T[][number]]: K; }>; declare function enums<T extends string>(values: readonly T[]): Struct<T, { [K in T[][number]]: K; }>; /** * Ensure that a value is a function. */ declare function func(): Struct<Function, null>; /** * Ensure that a value is an instance of a specific class. */ declare function instance<T extends { new (...args: any): any; }>(Class: T): Struct<InstanceType<T>, null>; /** * Ensure that a value is an integer. */ declare function integer(): Struct<number, null>; /** * Ensure that a value matches all of a set of types. */ declare function intersection<A>(Structs: TupleSchema<[ A ]>): Struct<A, null>; declare function intersection<A, B>(Structs: TupleSchema<[ A, B ]>): Struct<A & B, null>; declare function intersection<A, B, C>(Structs: TupleSchema<[ A, B, C ]>): Struct<A & B & C, null>; declare function intersection<A, B, C, D>(Structs: TupleSchema<[ A, B, C, D ]>): Struct<A & B & C & D, null>; declare function intersection<A, B, C, D, E>(Structs: TupleSchema<[ A, B, C, D, E ]>): Struct<A & B & C & D & E, null>; declare function intersection<A, B, C, D, E, F>(Structs: TupleSchema<[ A, B, C, D, E, F ]>): Struct<A & B & C & D & E & F, null>; declare function intersection<A, B, C, D, E, F, G>(Structs: TupleSchema<[ A, B, C, D, E, F, G ]>): Struct<A & B & C & D & E & F & G, null>; declare function intersection<A, B, C, D, E, F, G, H>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H ]>): Struct<A & B & C & D & E & F & G & H, null>; declare function intersection<A, B, C, D, E, F, G, H, I>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I ]>): Struct<A & B & C & D & E & F & G & H & I, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J ]>): Struct<A & B & C & D & E & F & G & H & I & J, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K ]>): Struct<A & B & C & D & E & F & G & H & I & J & K, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L, M>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L & M, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L, M, N>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L & M & N, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L & M & N & O, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L & M & N & O & P, null>; declare function intersection<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q ]>): Struct<A & B & C & D & E & F & G & H & I & J & K & L & M & N & O & P & Q, null>; /** * Ensure that a value is an exact value, using `===` for comparison. */ declare function literal<T extends boolean>(constant: T): Struct<T, null>; declare function literal<T extends number>(constant: T): Struct<T, null>; declare function literal<T extends string>(constant: T): Struct<T, null>; declare function literal<T>(constant: T): Struct<T, null>; /** * Ensure that a value is a `Map` object, and that its keys and values are of * specific types. */ declare function map(): Struct<Map<unknown, unknown>, null>; declare function map<K, V>(Key: Struct<K>, Value: Struct<V>): Struct<Map<K, V>, null>; /** * Ensure that no value ever passes validation. */ declare function never(): Struct<never, null>; /** * Augment an existing struct to allow `null` values. */ declare function nullable<T, S>(struct: Struct<T, S>): Struct<T | null, S>; /** * Ensure that a value is a number. */ declare function number(): Struct<number, null>; /** * Ensure that a value is an object, that is has a known set of properties, * and that its properties are of specific types. * * Note: Unrecognized properties will fail validation. */ declare function object(): Struct<Record<string, unknown>, null>; declare function object<S extends ObjectSchema>(schema: S): Struct<ObjectType<S>, S>; /** * Augment a struct to allow `undefined` values. */ declare function optional<T, S>(struct: Struct<T, S>): Struct<T | undefined, S>; /** * Ensure that a value is an object with keys and values of specific types, but * without ensuring any specific shape of properties. * * Like TypeScript's `Record` utility. */ declare function record<K extends string, V>(Key: Struct<K>, Value: Struct<V>): Struct<Record<K, V>, null>; /** * Ensure that a value is a `RegExp`. * * Note: this does not test the value against the regular expression! For that * you need to use the `pattern()` refinement. */ declare function regexp(): Struct<RegExp, null>; /** * Ensure that a value is a `Set` object, and that its elements are of a * specific type. */ declare function set(): Struct<Set<unknown>, null>; declare function set<T>(Element: Struct<T>): Struct<Set<T>, null>; /** * Ensure that a value is a string. */ declare function string(): Struct<string, null>; /** * Ensure that a value is a tuple of a specific length, and that each of its * elements is of a specific type. */ declare function tuple<A>(Structs: TupleSchema<[ A ]>): Struct<[ A ], null>; declare function tuple<A, B>(Structs: TupleSchema<[ A, B ]>): Struct<[ A, B ], null>; declare function tuple<A, B, C>(Structs: TupleSchema<[ A, B, C ]>): Struct<[ A, B, C ], null>; declare function tuple<A, B, C, D>(Structs: TupleSchema<[ A, B, C, D ]>): Struct<[ A, B, C, D ], null>; declare function tuple<A, B, C, D, E>(Structs: TupleSchema<[ A, B, C, D, E ]>): Struct<[ A, B, C, D, E ], null>; declare function tuple<A, B, C, D, E, F>(Structs: TupleSchema<[ A, B, C, D, E, F ]>): Struct<[ A, B, C, D, E, F ], null>; declare function tuple<A, B, C, D, E, F, G>(Structs: TupleSchema<[ A, B, C, D, E, F, G ]>): Struct<[ A, B, C, D, E, F, G ], null>; declare function tuple<A, B, C, D, E, F, G, H>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H ]>): Struct<[ A, B, C, D, E, F, G, H ], null>; declare function tuple<A, B, C, D, E, F, G, H, I>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I ]>): Struct<[ A, B, C, D, E, F, G, H, I ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J ]>): Struct<[ A, B, C, D, E, F, G, H, I, J ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L, M>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L, M ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ], null>; declare function tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q ]>): Struct<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q ], null>; /** * Ensure that a value has a set of known properties of specific types. * * Note: Unrecognized properties are allowed and untouched. This is similar to * how TypeScript's structural typing works. */ declare function type<S extends ObjectSchema>(schema: S): Struct<ObjectType<S>, S>; /** * Ensure that a value matches one of a set of types. */ declare function union<A>(Structs: TupleSchema<[ A ]>): Struct<A, null>; declare function union<A, B>(Structs: TupleSchema<[ A, B ]>): Struct<A | B, null>; declare function union<A, B, C>(Structs: TupleSchema<[ A, B, C ]>): Struct<A | B | C, null>; declare function union<A, B, C, D>(Structs: TupleSchema<[ A, B, C, D ]>): Struct<A | B | C | D, null>; declare function union<A, B, C, D, E>(Structs: TupleSchema<[ A, B, C, D, E ]>): Struct<A | B | C | D | E, null>; declare function union<A, B, C, D, E, F>(Structs: TupleSchema<[ A, B, C, D, E, F ]>): Struct<A | B | C | D | E | F, null>; declare function union<A, B, C, D, E, F, G>(Structs: TupleSchema<[ A, B, C, D, E, F, G ]>): Struct<A | B | C | D | E | F | G, null>; declare function union<A, B, C, D, E, F, G, H>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H ]>): Struct<A | B | C | D | E | F | G | H, null>; declare function union<A, B, C, D, E, F, G, H, I>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I ]>): Struct<A | B | C | D | E | F | G | H | I, null>; declare function union<A, B, C, D, E, F, G, H, I, J>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J ]>): Struct<A | B | C | D | E | F | G | H | I | J, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K ]>): Struct<A | B | C | D | E | F | G | H | I | J | K, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L, M>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L | M, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L, M, N>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L | M | N, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L | M | N | O, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P, null>; declare function union<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>(Structs: TupleSchema<[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q ]>): Struct<A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q, null>; /** * Ensure that any value passes validation, without widening its type to `any`. */ declare function unknown(): Struct<unknown, null>; /** * Create a new struct that combines the properties properties from multiple * object structs. * * Like JavaScript's `Object.assign` utility. */ declare function assign<A extends ObjectSchema, B extends ObjectSchema>(A: Struct<ObjectType<A>, A>, B: Struct<ObjectType<B>, B>): Struct<ObjectType<Assign<A, B>>, Assign<A, B>>; declare function assign<A extends ObjectSchema, B extends ObjectSchema, C extends ObjectSchema>(A: Struct<ObjectType<A>, A>, B: Struct<ObjectType<B>, B>, C: Struct<ObjectType<C>, C>): Struct<ObjectType<Assign<Assign<A, B>, C>>, Assign<Assign<A, B>, C>>; declare function assign<A extends ObjectSchema, B extends ObjectSchema, C extends ObjectSchema, D extends ObjectSchema>(A: Struct<ObjectType<A>, A>, B: Struct<ObjectType<B>, B>, C: Struct<ObjectType<C>, C>, D: Struct<ObjectType<D>, D>): Struct<ObjectType<Assign<Assign<Assign<A, B>, C>, D>>, Assign<Assign<Assign<A, B>, C>, D>>; declare function assign<A extends ObjectSchema, B extends ObjectSchema, C extends ObjectSchema, D extends ObjectSchema, E extends ObjectSchema>(A: Struct<ObjectType<A>, A>, B: Struct<ObjectType<B>, B>, C: Struct<ObjectType<C>, C>, D: Struct<ObjectType<D>, D>, E: Struct<ObjectType<E>, E>): Struct<ObjectType<Assign<Assign<Assign<Assign<A, B>, C>, D>, E>>, Assign<Assign<Assign<Assign<A, B>, C>, D>, E>>; /** * Define a new struct type with a custom validation function. */ declare function define<T>(name: string, validator: Validator): Struct<T, null>; /** * Create a struct with dynamic validation logic. * * The callback will receive the value currently being validated, and must * return a struct object to validate it with. This can be useful to model * validation logic that changes based on its input. */ declare function dynamic<T>(fn: (value: unknown, ctx: Context) => Struct<T, any>): Struct<T, null>; /** * Create a struct with lazily evaluated validation logic. * * The first time validation is run with the struct, the callback will be called * and must return a struct object to use. This is useful for cases where you * want to have self-referential structs for nested data structures to avoid a * circular definition problem. */ declare function lazy<T>(fn: () => Struct<T, any>): Struct<T, null>; /** * Create a new struct based on an existing object struct, but excluding * specific properties. * * Like TypeScript's `Omit` utility. */ declare function omit<S extends ObjectSchema, K extends keyof S>(struct: Struct<ObjectType<S>, S>, keys: K[]): Struct<ObjectType<Omit<S, K>>, Omit<S, K>>; /** * Create a new struct based on an existing object struct, but with all of its * properties allowed to be `undefined`. * * Like TypeScript's `Partial` utility. */ declare function partial<S extends ObjectSchema>(struct: Struct<ObjectType<S>, S> | S): Struct<ObjectType<PartialObjectSchema<S>>, PartialObjectSchema<S>>; /** * Create a new struct based on an existing object struct, but only including * specific properties. * * Like TypeScript's `Pick` utility. */ declare function pick<S extends ObjectSchema, K extends keyof S>(struct: Struct<ObjectType<S>, S>, keys: K[]): Struct<ObjectType<Pick<S, K>>, Pick<S, K>>; /** * Define a new struct type with a custom validation function. * * @deprecated This function has been renamed to `define`. */ declare function struct<T>(name: string, validator: Validator): Struct<T, null>; export { Failure, StructError, Struct, assert, create, mask, is, validate, Context, Infer, Describe, Result, Coercer, Validator, Refiner, coerce, defaulted, trimmed, empty, max, min, pattern, size, refine, any, array, boolean, date, enums, func, instance, integer, intersection, literal, map, never, nullable, number, object, optional, record, regexp, set, string, tuple, type, union, unknown, assign, define, dynamic, lazy, omit, partial, pick, struct };