UNPKG

runtypes

Version:

Runtime validation for static types

89 lines (88 loc) 4.25 kB
import Optional from "./Optional.js"; import Runtype, { type Parsed, type Static } from "./Runtype.js"; type OptionalKeysStatic<T> = { [K in keyof T]: T[K] extends Optional ? K : never; }[keyof T]; type RequiredKeysStatic<T> = { [K in keyof T]: T[K] extends Optional ? never : K; }[keyof T]; type OptionalKeysParsed<T> = { [K in keyof T]: T[K] extends Optional<any, infer X> ? ([X] extends [never] ? K : never) : never; }[keyof T]; type RequiredKeysParsed<T> = { [K in keyof T]: T[K] extends Optional<any, infer X> ? ([X] extends [never] ? never : K) : K; }[keyof T]; type RequiredValuesStatic<T> = T extends Runtype.Core ? Static<T> : never; type OptionalValuesStatic<T> = T extends Optional<infer OK> ? Static<OK> : never; type RequiredValuesParsed<T> = T extends Optional<infer OK, infer X> ? [X] extends [never] ? never : Parsed<OK> | X : T extends Runtype.Core ? Parsed<T> : never; type OptionalValuesParsed<T> = T extends Optional<infer OK, infer X> ? ([X] extends [never] ? Parsed<OK> : never) : never; type ObjectStaticReadonly<O extends Object.Fields> = { [K in RequiredKeysStatic<O>]: RequiredValuesStatic<O[K]>; } & { [K in OptionalKeysStatic<O>]?: OptionalValuesStatic<O[K]>; } extends infer P ? { readonly [K in keyof P]: P[K]; } : never; type ObjectStatic<O extends Object.Fields> = { [K in RequiredKeysStatic<O>]: RequiredValuesStatic<O[K]>; } & { [K in OptionalKeysStatic<O>]?: OptionalValuesStatic<O[K]>; } extends infer P ? { [K in keyof P]: P[K]; } : never; type ObjectParsedReadonly<O extends Object.Fields> = { [K in RequiredKeysParsed<O>]: RequiredValuesParsed<O[K]>; } & { [K in OptionalKeysParsed<O>]?: OptionalValuesParsed<O[K]>; } extends infer P ? { readonly [K in keyof P]: P[K]; } : never; type ObjectParsed<O extends Object.Fields> = { [K in RequiredKeysParsed<O>]: RequiredValuesParsed<O[K]>; } & { [K in OptionalKeysParsed<O>]?: OptionalValuesParsed<O[K]>; } extends infer P ? { [K in keyof P]: P[K]; } : never; type Utilities<O extends Object.Fields> = { asPartial(): Object<{ [K in keyof O]: O[K] extends Optional ? O[K] : O[K] extends Runtype.Core ? Optional<O[K]> : never; }>; asReadonly(): Object.Readonly<O>; pick<K extends keyof O = never>(...keys: K[]): Object<Pick<O, K>>; omit<K extends keyof O = never>(...keys: K[]): Object<Omit<O, K>>; extend<P extends Object.Fields>(fields: { [K in keyof P]: K extends keyof O ? O[K] extends Optional<infer OK> ? P[K] extends Optional<infer PK> ? Static<PK> extends Static<OK> ? P[K] : Runtype.Core<Static<OK>> | Optional<Runtype.Core<Static<OK>>> : P[K] extends Runtype.Core ? P[K] extends OK ? P[K] : Runtype.Core<Static<OK>> | Optional<Runtype.Core<Static<OK>>> : never : O[K] extends Runtype.Core ? P[K] extends Optional ? Runtype.Core<Static<O[K]>> : P[K] extends Runtype.Core ? Static<P[K]> extends Static<O[K]> ? P[K] : Runtype.Core<Static<O[K]>> : never : never : P[K]; }): Object<{ [K in keyof O | keyof P]: K extends keyof P ? P[K] : K extends keyof O ? O[K] : never; }>; exact(): Object<O>; }; /** * Validates that a value is an object and each property fulfills the given property runtype. * * Possible failures: * * - `TYPE_INCORRECT` for `null`, `undefined`, and non-objects if fields were non-empty * - `CONTENT_INCORRECT` with `details` reporting the failed properties * * For each property, contextual failures can be seen in addition to failures of the property runtype: * * - `PROPERTY_MISSING` for missing required properties * - `PROPERTY_PRESENT` for extraneous properties where `.exact()` flag is enabled */ interface Object<O extends Object.Fields = Object.Fields> extends Runtype<ObjectStatic<O>, ObjectParsed<O>>, Utilities<O> { tag: "object"; fields: O; isExact: boolean; } declare namespace Object { type Fields = globalThis.Record<PropertyKey, Runtype.Core | Optional>; interface Readonly<O extends Object.Fields = Object.Fields> extends Runtype<ObjectStaticReadonly<O>, ObjectParsedReadonly<O>>, Utilities<O> { tag: "object"; fields: O; isExact: boolean; } } declare const Object: <O extends Object.Fields>(fields: O) => Object<O>; export default Object;