UNPKG

@winhillsen/joi-extract-type

Version:

Provides native type extraction from Joi schemas for Typescript

66 lines (65 loc) 4.58 kB
import "joi"; export { tuple } from './tuple'; declare module "joi" { type primitiveType = string | number | boolean | Function | Date | undefined | null | void; type schemaMap = { [key: string]: mappedSchema; }; type mappedSchema = SchemaLike | mappedSchemaMap; type mappedSchemaMap<T extends schemaMap = any> = { [K in keyof T]: T[K]; }; interface StringSchema<N = string> extends AnySchema { valid<T extends string>(...values: T[]): StringSchema<typeof values[number]>; valid<T extends string[]>(values: T): StringSchema<typeof values[number]>; valid(...values: any[]): this; valid(values: any[]): this; } function string<T extends string>(): StringSchema<extractType<T>>; interface ArraySchema<N = any> extends AnySchema { items<T extends mappedSchema>(type: T): ArraySchema<extractType<T>>; } interface ObjectSchema<N = any> extends AnySchema { keys<T extends mappedSchemaMap>(schema: T): ObjectSchema<extractMap<N & T>>; } function object<T extends mappedSchemaMap>(schema: T): ObjectSchema<extractMap<T>>; interface FunctionSchema<N = any> extends AnySchema { } function func<T extends Function>(): FunctionSchema<T>; interface AlternativesSchema<T1 extends mappedSchema = never, T2 extends mappedSchema = never, T3 extends mappedSchema = never, T4 extends mappedSchema = never, T5 extends mappedSchema = never> extends AnySchema { } function alternatives<T1 extends mappedSchema, T2 extends mappedSchema, T3 extends mappedSchema, T4 extends mappedSchema, T5 extends mappedSchema>(a: T1, b: T2, c: T3, d: T4, e: T5): AlternativesSchema<extractType<T1>, extractType<T2>, extractType<T3>, extractType<T4>, extractType<T5>>; function alternatives<T1 extends mappedSchema, T2 extends mappedSchema, T3 extends mappedSchema, T4 extends mappedSchema>(a: T1, b: T2, c: T3, d: T4): AlternativesSchema<extractType<T1>, extractType<T2>, extractType<T3>, extractType<T4>>; function alternatives<T1 extends mappedSchema, T2 extends mappedSchema, T3 extends mappedSchema>(a: T1, b: T2, c: T3): AlternativesSchema<extractType<T1>, extractType<T2>, extractType<T3>>; function alternatives<T1 extends mappedSchema, T2 extends mappedSchema>(a: T1, b: T2): AlternativesSchema<extractType<T1>, extractType<T2>>; type extractMap<T> = { [K in keyof T]: extractType<T[K]>; }; type extractType<T extends mappedSchema> = T extends primitiveType ? T : T extends BooleanSchema ? boolean : T extends StringSchema<infer O> ? O : T extends NumberSchema ? number : T extends DateSchema ? Date : T extends FunctionSchema<infer O> ? O : /** Holds the extracted type */ T extends ArraySchema<infer O> ? O[] : T extends ObjectSchema<infer O> ? O : T extends mappedSchemaMap<infer O> ? O : /** * Supports Joi.alternatives(Schema1, schema2, ...5) * * I think there is a better way of writing this, * but couldn't find it at the moment. */ T extends AlternativesSchema<infer O1, infer O2, infer O3, infer O4, infer O5> ? O1 | O2 | O3 | O4 | O5 : T extends AlternativesSchema<infer O1, infer O2, infer O3, infer O4> ? O1 | O2 | O3 | O4 : T extends AlternativesSchema<infer O1, infer O2, infer O3> ? O1 | O2 | O3 : T extends AlternativesSchema<infer O1, infer O2> ? O1 | O2 : /** * Hack to support [Schema1, Schema2, ...N] alternatives notation * * Can't use extractType because of cycles: * ``` * T extends Array<infer O> ? extractType<O> : * ^ cycle * ``` * * So one option was to dupplicate extractType here. * Im sure we could write it without these dupplication, * but some aliasing techinique would be necessary to * allow the cycling * * It is ugly but acctualy works well */ T extends Array<infer O> ? (O extends primitiveType ? O : O extends BooleanSchema ? boolean : O extends StringSchema<infer O> ? O : O extends NumberSchema ? number : O extends DateSchema ? Date : O extends FunctionSchema<infer O> ? O : O extends ArraySchema<infer O> ? O[] : O extends ObjectSchema<infer O> ? O : O extends mappedSchemaMap<infer O> ? O : O extends AlternativesSchema<infer O1, infer O2, infer O3, infer O4, infer O5> ? O1 | O2 | O3 | O4 | O5 : O extends AlternativesSchema<infer O1, infer O2, infer O3, infer O4> ? O1 | O2 | O3 | O4 : O extends AlternativesSchema<infer O1, infer O2, infer O3> ? O1 | O2 | O3 : O extends AlternativesSchema<infer O1, infer O2> ? O1 | O2 : any) : any; }