Skip to content

Commit

Permalink
fix: narrow down types in case of {}
Browse files Browse the repository at this point in the history
  • Loading branch information
5alidz committed Apr 5, 2021
1 parent 6d42bd0 commit 5cf59cf
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/createErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ export function createErrors<T extends Schema>(schema: T, data: any, eager = fal
if (!isBool(value)) return TYPEERR;
return null;
},
list: ({ validator, value }) => {
list: ({ validator, value }): {} | null | typeof TYPEERR => {
// NOTE: because null signals continue recursively
// we return an empty object to skip its children
if (shouldSkipValidation(value, validator)) return {};
if (!Array.isArray(value)) return TYPEERR;
return null;
},
record: ({ validator, value }) => {
record: ({ validator, value }): {} | null | typeof TYPEERR => {
// NOTE: because null signals continue recursively
// we return an empty object to skip its children
if (shouldSkipValidation(value, validator)) return {};
Expand Down
47 changes: 34 additions & 13 deletions src/traverse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
RecordofValidator,
ListValidator,
ListofValidator,
StringValidator,
NumberValidator,
BooleanValidator,
} from './validatorTypes';

function normalizeResult(result: Record<string, any>) {
Expand All @@ -25,34 +28,52 @@ export type Visitor = Partial<
}
>;

type VisitorExists<Vi extends Visitor, Def, VKey extends VisitorMember> = Vi[VKey] extends undefined
? NonNullable<Def> | undefined
: ReturnType<NonNullable<Vi[VKey]>> extends infer X | null | undefined
? X extends {} | [] | null
? NonNullable<Def> | undefined
: NonNullable<Def> | NonNullable<X> | undefined
: ReturnType<NonNullable<Vi[VKey]>>;
type VisitorExists<
Vi extends Visitor,
Default,
VKey extends VisitorMember
> = Vi[VKey] extends undefined
? never
: ReturnType<NonNullable<Vi[VKey]>> extends infer X
? X extends string | number | boolean | null | undefined
? NonNullable<Default> | NonNullable<X>
: X extends {}
? NonNullable<Default>
: NonNullable<Default> | NonNullable<X>
: NonNullable<Default>;

type InferVisitorResult<V extends Validator, Vi extends Visitor> = V extends RecordValidator<
infer S
>
? VisitorExists<Vi, { [K in keyof S]?: NonNullable<InferVisitorResult<S[K], Vi>> }, 'record'>
: V extends ListValidator<infer A>
? VisitorExists<Vi, NonNullable<InferVisitorResult<A[number], Vi>>[], 'list'>
? VisitorExists<
Vi,
{ [K in number]: NonNullable<InferVisitorResult<A[number], Vi>> | undefined },
'list'
>
: V extends ListofValidator<infer VV>
? VisitorExists<Vi, NonNullable<InferVisitorResult<VV, Vi>>[], 'listof'>
? VisitorExists<
Vi,
{ [key: number]: NonNullable<InferVisitorResult<VV, Vi>> | undefined },
'listof'
>
: V extends RecordofValidator<infer VV>
? VisitorExists<
Vi,
{ [key: string]: NonNullable<InferVisitorResult<VV, Vi>> | undefined },
'recordof'
>
: Vi[V['type']] extends void
? undefined
: ReturnType<NonNullable<Vi[V['type']]>>;
: V extends StringValidator
? VisitorExists<Vi, ReturnType<NonNullable<Vi['string']>>, 'string'>
: V extends NumberValidator
? VisitorExists<Vi, ReturnType<NonNullable<Vi['number']>>, 'number'>
: V extends BooleanValidator
? VisitorExists<Vi, ReturnType<NonNullable<Vi['boolean']>>, 'boolean'>
: never;

export type TraverseResult<S extends Schema, V extends Visitor> = {
[K in keyof S]: NonNullable<InferVisitorResult<S[K], V>>;
[K in keyof S]: InferVisitorResult<S[K], V>;
};

function enterNode(
Expand Down

0 comments on commit 5cf59cf

Please sign in to comment.