Skip to content

Commit

Permalink
fix: tuple describe() method (#1947)
Browse files Browse the repository at this point in the history
* Add tuple.describe()

* Undo clone method change

* Use types instead of innerType, use proper describe arg

* Undo array changes

* Update array spec

* Update types and spec
  • Loading branch information
DaddyWarbucks authored Mar 23, 2023
1 parent f37a53f commit 297f168
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 6 deletions.
13 changes: 12 additions & 1 deletion src/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,23 @@ export function create<C extends Maybe<AnyObject> = AnyObject, T = any>(
return new ArraySchema<T[] | undefined, C>(type as any);
}

interface ArraySchemaSpec<TIn, TContext> extends SchemaSpec<any> {
types?: ISchema<InnerType<TIn>, TContext>
}

export default class ArraySchema<
TIn extends any[] | null | undefined,
TContext,
TDefault = undefined,
TFlags extends Flags = '',
> extends Schema<TIn, TContext, TDefault, TFlags> {
declare spec: ArraySchemaSpec<TIn, TContext>;
readonly innerType?: ISchema<InnerType<TIn>, TContext>;

constructor(type?: ISchema<InnerType<TIn>, TContext>) {
super({
type: 'array',
spec: { types: type } as ArraySchemaSpec<TIn, TContext>,
check(v: any): v is NonNullable<TIn> {
return Array.isArray(v);
},
Expand Down Expand Up @@ -183,6 +189,11 @@ export default class ArraySchema<
// @ts-expect-error readonly
next.innerType = schema;

next.spec = {
...next.spec,
types: schema as ISchema<InnerType<TIn>, TContext>
}

return next as any;
}

Expand Down Expand Up @@ -263,7 +274,7 @@ export default class ArraySchema<
value: innerOptions.value[0],
};
}
base.innerType = this.innerType.describe(options);
base.innerType = this.innerType.describe(innerOptions);
}
return base;
}
Expand Down
2 changes: 1 addition & 1 deletion src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export interface SchemaRefDescription {
}

export interface SchemaInnerTypeDescription extends SchemaDescription {
innerType?: SchemaFieldDescription;
innerType?: SchemaFieldDescription | SchemaFieldDescription[];
}

export interface SchemaObjectDescription extends SchemaDescription {
Expand Down
23 changes: 22 additions & 1 deletion src/tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import type {
UnsetFlag,
Maybe,
} from './util/types';
import Schema, { RunTest, SchemaSpec } from './schema';
import type { ResolveOptions } from './Condition';
import Schema, {
RunTest,
SchemaInnerTypeDescription,
SchemaSpec,
} from './schema';
import ValidationError from './ValidationError';
import { tuple as tupleLocale } from './locale';

Expand Down Expand Up @@ -148,6 +153,22 @@ export default class TupleSchema<
);
});
}

describe(options?: ResolveOptions<TContext>) {
let base = super.describe(options) as SchemaInnerTypeDescription;
base.innerType = this.spec.types.map((schema, index) => {
let innerOptions = options;
if (innerOptions?.value) {
innerOptions = {
...innerOptions,
parent: innerOptions.value,
value: innerOptions.value[index],
};
}
return schema.describe(innerOptions);
});
return base;
}
}

create.prototype = TupleSchema.prototype;
78 changes: 76 additions & 2 deletions test/mixed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ref,
Schema,
string,
tuple,
ValidationError,
} from '../src';
import ObjectSchema from '../src/object';
Expand Down Expand Up @@ -965,6 +966,7 @@ describe('Mixed Types ', () => {
is: 'entered',
then: (s) => s.defined(),
}),
baz: tuple([string(), number()])
});
});

Expand All @@ -976,7 +978,8 @@ describe('Mixed Types ', () => {
default: {
foo: undefined,
bar: 'a',
lazy: undefined
lazy: undefined,
baz: undefined,
},
nullable: false,
optional: true,
Expand Down Expand Up @@ -1035,6 +1038,41 @@ describe('Mixed Types ', () => {
},
],
},
baz: {
type: 'tuple',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
tests: [],
oneOf: [],
notOneOf: [],
innerType: [
{
type: 'string',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
oneOf: [],
notOneOf: [],
tests: [],
},
{
type: 'number',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
oneOf: [],
notOneOf: [],
tests: [],
}
],
},
},
});
});
Expand All @@ -1047,7 +1085,8 @@ describe('Mixed Types ', () => {
default: {
foo: undefined,
bar: 'a',
lazy: undefined
lazy: undefined,
baz: undefined,
},
nullable: false,
optional: true,
Expand Down Expand Up @@ -1111,6 +1150,41 @@ describe('Mixed Types ', () => {
},
],
},
baz: {
type: 'tuple',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
tests: [],
oneOf: [],
notOneOf: [],
innerType: [
{
type: 'string',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
oneOf: [],
notOneOf: [],
tests: [],
},
{
type: 'number',
meta: undefined,
label: undefined,
default: undefined,
nullable: false,
optional: true,
oneOf: [],
notOneOf: [],
tests: [],
}
],
},
},
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('Array types', () => {
);
});

it('should throw useful type error for lenght', async () => {
it('should throw useful type error for length', async () => {
let schema = tuple([string().label('name'), number().label('age')]);

// expect(() => schema.cast(['James'])).toThrowError(
Expand Down

0 comments on commit 297f168

Please sign in to comment.