export type SpectypesError< X extends string, Y extends string, Suf extends string = '' > = PrettyType<{ readonly [key in `spectypes error: '${X}' can't appear directly inside '${Y}'${Suf}`]: never }> export type SuccessResult = { readonly tag: 'success' readonly success: Value } export type FailureResult = { readonly tag: 'failure' readonly failure: { readonly value: unknown readonly errors: ReadonlyArray<{ readonly issue: string readonly path: ReadonlyArray }> } } export type Result = FailureResult | SuccessResult export type SuccessOf> = R extends SuccessResult ? Success : never export type SpecConfig = { readonly tag: Tag readonly kind: Kind } export type Spec< Tag extends readonly string[] = readonly string[], Kind extends string = string, Value = unknown > = ((value: unknown) => Result) & { readonly config?: SpecConfig } export type SpecSuccess = SuccessOf> export type SpecTag = Required['config'] extends SpecConfig< infer Tag, string > ? Tag : never export type SpecKind = Required['config'] extends SpecConfig< readonly string[], infer Kind > ? Kind : never export type SpecsTags = Specs extends readonly [ infer First, ...infer Rest ] ? First extends Spec ? Rest extends readonly Spec[] ? readonly [...SpecTag, ...SpecsTags] : readonly [] : readonly [] : readonly [] export type HasTag = { readonly [Index in keyof SpecTag]: Tags extends SpecTag[Index] ? true : false }[number] // source: https://github.com/badrap/valita/blob/v0.1.1/src/index.ts export type PrettyType = Extract<{ [K in keyof V]: V[K] }, unknown> export type OmitByValue = Omit< Rec, { readonly [Key in keyof Rec]: Rec[Key] extends Value ? Key : never }[keyof Rec] > export type ObjectValue> = PrettyType< OmitByValue< { readonly [Key in keyof Specs]: Specs[Key] extends Spec ? HasTag extends true ? never : SpecSuccess : never }, never > & OmitByValue< { readonly [Key in keyof Specs]?: Specs[Key] extends Spec ? HasTag extends true ? SpecSuccess : never : never }, never | undefined > > // eslint-disable-next-line @typescript-eslint/ban-types export type LiteralBase = string | number | boolean | undefined | null export type InferKind = Specs extends readonly [ infer First, ...infer Rest ] ? First extends Spec ? 'transformer' : Rest extends readonly Spec[] ? InferKind : 'validator' : 'validator' export type SomeSpec = Spec<[''], '', unknown>