From 72269c433e503a3024abcd339db22cc7fd7582f0 Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Mon, 13 Sep 2021 19:08:44 -0700 Subject: [PATCH] types: Update schema validation to use unknown. --- optimal/src/createSchema.ts | 8 ++++---- optimal/src/schemas/date.ts | 4 ++-- optimal/src/schemas/shape.ts | 2 +- optimal/src/types.ts | 10 +++------- optimal/tests/schemas/array.test.ts | 2 -- optimal/tests/schemas/blueprint.test.ts | 2 -- optimal/tests/schemas/bool.test.ts | 3 --- optimal/tests/schemas/custom.test.ts | 1 - optimal/tests/schemas/date.test.ts | 1 - optimal/tests/schemas/func.test.ts | 3 +-- optimal/tests/schemas/lazy.test.ts | 1 - optimal/tests/schemas/number.test.ts | 2 -- optimal/tests/schemas/object.test.ts | 2 -- optimal/tests/schemas/regex.test.ts | 2 -- optimal/tests/schemas/schema.test.ts | 4 ---- optimal/tests/schemas/shape.test.ts | 2 -- optimal/tests/schemas/string.test.ts | 2 -- optimal/tests/schemas/tuple.test.ts | 4 ---- optimal/tests/schemas/union.test.ts | 16 +--------------- 19 files changed, 12 insertions(+), 59 deletions(-) diff --git a/optimal/src/createSchema.ts b/optimal/src/createSchema.ts index 7f1f4a0..35799a1 100644 --- a/optimal/src/createSchema.ts +++ b/optimal/src/createSchema.ts @@ -20,7 +20,7 @@ import { function validate( state: SchemaState, validators: Criteria[], - initialValue: T | null | undefined, + initialValue: unknown, path: string = '', { collectErrors = true, @@ -30,7 +30,7 @@ function validate( ): T | null { const { defaultValue, metadata } = state; - let value: T | null | undefined = initialValue; + let value: unknown = initialValue; // Handle undefined if (value === undefined) { @@ -67,7 +67,7 @@ function validate( tryAndCollect( () => { - const result = test.validate(value!, path, { + const result = test.validate(value as T, path, { collectErrors, currentObject, rootObject, @@ -86,7 +86,7 @@ function validate( throw optimalError; } - return value!; + return value as T; } export function createSchema>( diff --git a/optimal/src/schemas/date.ts b/optimal/src/schemas/date.ts index 742ffcc..e942c95 100644 --- a/optimal/src/schemas/date.ts +++ b/optimal/src/schemas/date.ts @@ -1,10 +1,10 @@ import { createSchema } from '../createSchema'; import { commonCriteria, dateCriteria } from '../criteria'; import { createDate, invalid, isValidDate } from '../helpers'; -import { CommonCriterias, DateCriterias, DefaultValue, MaybeDate, Schema } from '../types'; +import { CommonCriterias, DateCriterias, DefaultValue, Schema } from '../types'; export interface DateSchema - extends Schema, + extends Schema, DateCriterias>, CommonCriterias> { never: () => DateSchema; diff --git a/optimal/src/schemas/shape.ts b/optimal/src/schemas/shape.ts index 4b21f3e..c76acbf 100644 --- a/optimal/src/schemas/shape.ts +++ b/optimal/src/schemas/shape.ts @@ -4,7 +4,7 @@ import { createObject, invalid, isObject } from '../helpers'; import { Blueprint, CommonCriterias, InferNullable, Schema, ShapeCriterias } from '../types'; export interface ShapeSchema - extends Schema>, + extends Schema, ShapeCriterias>, CommonCriterias> { never: () => ShapeSchema; diff --git a/optimal/src/types.ts b/optimal/src/types.ts index 36832a1..a835837 100644 --- a/optimal/src/types.ts +++ b/optimal/src/types.ts @@ -126,14 +126,10 @@ export interface SchemaValidateOptions { rootObject?: UnknownObject; } -export interface Schema { +export interface Schema { schema: () => string; type: () => string; - validate: ( - value: Input | null | undefined, - path?: string, - options?: SchemaValidateOptions, - ) => Output; + validate: (value: unknown, path?: string, options?: SchemaValidateOptions) => Output; } export interface SchemaState { @@ -180,6 +176,6 @@ export type DeepPartial = T extends Function // Any is required for generics to be typed correctly for consumers /* eslint-disable @typescript-eslint/no-explicit-any */ -export type AnySchema = Schema; +export type AnySchema = Schema; export type AnyFunction = (...args: any[]) => any; diff --git a/optimal/tests/schemas/array.test.ts b/optimal/tests/schemas/array.test.ts index 7a3d679..7a5cdf3 100644 --- a/optimal/tests/schemas/array.test.ts +++ b/optimal/tests/schemas/array.test.ts @@ -102,14 +102,12 @@ describe('array()', () => { it('errors if a non-array is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be an array.'); }); it('errors if array value type is invalid', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate([123]); }).toThrow('Must be a string.'); }); diff --git a/optimal/tests/schemas/blueprint.test.ts b/optimal/tests/schemas/blueprint.test.ts index 0fe6567..a7b9fcf 100644 --- a/optimal/tests/schemas/blueprint.test.ts +++ b/optimal/tests/schemas/blueprint.test.ts @@ -21,14 +21,12 @@ describe('blueprint()', () => { describe('validateType()', () => { it('errors if a non-object is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a plain object.'); }); it('errors if a value is not a schema', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({ foo: 123 }); }).toThrow('Must be a schema.'); }); diff --git a/optimal/tests/schemas/bool.test.ts b/optimal/tests/schemas/bool.test.ts index b7724dd..54aa23a 100644 --- a/optimal/tests/schemas/bool.test.ts +++ b/optimal/tests/schemas/bool.test.ts @@ -29,7 +29,6 @@ describe('bool()', () => { it('errors if value is `true`', () => { expect(() => { - // @ts-expect-error Invalid type falseSchema.validate(true); }).toThrow('May only be `false`.'); }); @@ -62,7 +61,6 @@ describe('bool()', () => { it('errors if value is `false`', () => { expect(() => { - // @ts-expect-error Invalid type trueSchema.validate(false); }).toThrow('May only be `true`.'); }); @@ -95,7 +93,6 @@ describe('bool()', () => { describe('validateType()', () => { it('errors if a non-boolean is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a boolean.'); }); diff --git a/optimal/tests/schemas/custom.test.ts b/optimal/tests/schemas/custom.test.ts index 0583554..5191c5d 100644 --- a/optimal/tests/schemas/custom.test.ts +++ b/optimal/tests/schemas/custom.test.ts @@ -62,7 +62,6 @@ describe('custom()', () => { it('errors if a non-string is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a string!!!'); }); diff --git a/optimal/tests/schemas/date.test.ts b/optimal/tests/schemas/date.test.ts index ced126d..28130de 100644 --- a/optimal/tests/schemas/date.test.ts +++ b/optimal/tests/schemas/date.test.ts @@ -185,7 +185,6 @@ describe('date()', () => { describe('validateType()', () => { it('errors if a non-date value is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate([]); }).toThrow('Must be a string, number, or `Date` that resolves to a valid date.'); }); diff --git a/optimal/tests/schemas/func.test.ts b/optimal/tests/schemas/func.test.ts index 964f90c..b8529b5 100644 --- a/optimal/tests/schemas/func.test.ts +++ b/optimal/tests/schemas/func.test.ts @@ -1,4 +1,4 @@ -import { AnyFunction,func, FunctionSchema, Infer } from '../../src'; +import { AnyFunction, func, FunctionSchema, Infer } from '../../src'; import { runCommonTests } from './runCommonTests'; describe('func()', () => { @@ -27,7 +27,6 @@ describe('func()', () => { describe('validateType()', () => { it('errors if a non-function is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a function.'); }); diff --git a/optimal/tests/schemas/lazy.test.ts b/optimal/tests/schemas/lazy.test.ts index 3d08535..e1ddc1e 100644 --- a/optimal/tests/schemas/lazy.test.ts +++ b/optimal/tests/schemas/lazy.test.ts @@ -119,7 +119,6 @@ describe('lazy()', () => { it('errors if valid values the lazy schema', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a string.'); diff --git a/optimal/tests/schemas/number.test.ts b/optimal/tests/schemas/number.test.ts index 68b26c5..c2b4395 100644 --- a/optimal/tests/schemas/number.test.ts +++ b/optimal/tests/schemas/number.test.ts @@ -31,7 +31,6 @@ describe('number()', () => { it('errors if number is not in list', () => { expect(() => { - // @ts-expect-error Invalid type oneOfSchema.validate(5); }).toThrow('Number must be one of: 1, 2, 3'); }); @@ -321,7 +320,6 @@ describe('number()', () => { describe('validateType()', () => { it('errors if a non-number is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate('abc'); }).toThrow('Must be a number.'); }); diff --git a/optimal/tests/schemas/object.test.ts b/optimal/tests/schemas/object.test.ts index 7273080..e1760d7 100644 --- a/optimal/tests/schemas/object.test.ts +++ b/optimal/tests/schemas/object.test.ts @@ -142,14 +142,12 @@ describe('object()', () => { it('errors if a non-object is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a plain object.'); }); it('errors if object value type is invalid', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({ a: 123 }); }).toThrow('Must be a string.'); }); diff --git a/optimal/tests/schemas/regex.test.ts b/optimal/tests/schemas/regex.test.ts index 6a6e021..2b109fd 100644 --- a/optimal/tests/schemas/regex.test.ts +++ b/optimal/tests/schemas/regex.test.ts @@ -24,14 +24,12 @@ describe('regex()', () => { describe('validateType()', () => { it('errors if a non-object is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be an instance of RegExp.'); }); it('errors if a plain object is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({}); }).toThrow('Must be an instance of RegExp.'); }); diff --git a/optimal/tests/schemas/schema.test.ts b/optimal/tests/schemas/schema.test.ts index e76df06..1c6f903 100644 --- a/optimal/tests/schemas/schema.test.ts +++ b/optimal/tests/schemas/schema.test.ts @@ -23,7 +23,6 @@ describe('schema()', () => { describe('validateType()', () => { it('errors if a non-object is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a schema.'); }); @@ -36,21 +35,18 @@ describe('schema()', () => { it('errors if a schema is not a function', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({ schema: 123 }); }).toThrow('Must be a function.'); }); it('errors if a type is not a function', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({ schema() {}, type: 123 }); }).toThrow('Must be a function.'); }); it('errors if a validate is not a function', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate({ schema() {}, type() {}, validate: 123 }); }).toThrow('Must be a function.'); }); diff --git a/optimal/tests/schemas/shape.test.ts b/optimal/tests/schemas/shape.test.ts index 153c748..4a1a358 100644 --- a/optimal/tests/schemas/shape.test.ts +++ b/optimal/tests/schemas/shape.test.ts @@ -60,7 +60,6 @@ describe('shape()', () => { it('errors if unknown properties passed', () => { expect(() => { - // @ts-expect-error Invalid type exactSchema.validate({ foo: '', bar: 0, baz: true, qux: 'unknown' }); }).toThrow('Unknown fields: qux.'); }); @@ -107,7 +106,6 @@ describe('shape()', () => { it('errors if a non-shape is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a shaped object.'); }); diff --git a/optimal/tests/schemas/string.test.ts b/optimal/tests/schemas/string.test.ts index 1bc6b3e..3236533 100644 --- a/optimal/tests/schemas/string.test.ts +++ b/optimal/tests/schemas/string.test.ts @@ -352,7 +352,6 @@ describe('string()', () => { it('errors if value is not in the list', () => { expect(() => { - // @ts-expect-error Invalid type oneOfSchema.validate('qux'); }).toThrowErrorMatchingInlineSnapshot(`"String must be one of: foo, bar, baz"`); }); @@ -571,7 +570,6 @@ describe('string()', () => { describe('validateType()', () => { it('errors if a non-string is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a string.'); }); diff --git a/optimal/tests/schemas/tuple.test.ts b/optimal/tests/schemas/tuple.test.ts index eb661e0..4b41316 100644 --- a/optimal/tests/schemas/tuple.test.ts +++ b/optimal/tests/schemas/tuple.test.ts @@ -58,14 +58,12 @@ describe('tuple()', () => { describe('validateType()', () => { it('errors if a non-tuple is passed', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate(123); }).toThrow('Must be a tuple.'); }); it('errors if the first tuple item is invalid', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate([null, false, 4, {}, 'foo']); }).toThrow('Null is not allowed.'); }); @@ -78,7 +76,6 @@ describe('tuple()', () => { it('errors if the last tuple item is invalid', () => { expect(() => { - // @ts-expect-error Invalid type schema.validate([[], false, 4, {}, 'qux']); }).toThrow('String must be one of: foo, bar, baz'); }); @@ -110,7 +107,6 @@ describe('tuple()', () => { }); it('returns the default value from its items when an empty array is passed', () => { - // @ts-expect-error Invalid type expect(schema.validate([])).toEqual([[], true, 1, {}, 'foo']); }); }); diff --git a/optimal/tests/schemas/union.test.ts b/optimal/tests/schemas/union.test.ts index ec4a829..ba208bc 100644 --- a/optimal/tests/schemas/union.test.ts +++ b/optimal/tests/schemas/union.test.ts @@ -59,10 +59,7 @@ describe('union()', () => { it('errors if a unsupported type is used', () => { expect(() => { - union(0) - .of([bool(), number(), string()]) - // @ts-expect-error Invalid type - .validate({}); + union(0).of([bool(), number(), string()]).validate({}); }).toThrowErrorMatchingInlineSnapshot(`"Value must be one of: boolean, number, string."`); }); @@ -78,7 +75,6 @@ describe('union()', () => { expect(() => { union(0) .of([number(), instance().of(Buffer)]) - // @ts-expect-error Invalid type .validate(new Foo()); }).toThrowErrorMatchingInlineSnapshot(` "Received class with the following failures: @@ -163,7 +159,6 @@ describe('union()', () => { }), ]) - // @ts-expect-error Invalid type .validate({ foo: 123 }); }).toThrowErrorMatchingInlineSnapshot(` "Received object/shape with the following failures: @@ -185,7 +180,6 @@ describe('union()', () => { expect(() => { union(['foo', 'bar', 'baz']) .of([tuple<['foo', 'bar', 'baz']>([string(), string(), string()])]) - // @ts-expect-error Invalid type .validate([1]); }).toThrowErrorMatchingInlineSnapshot(` "Received array/tuple with the following failures: @@ -206,7 +200,6 @@ describe('union()', () => { ]); expect(() => { - // @ts-expect-error Invalid type arrayUnion.validate([true]); }).toThrowErrorMatchingInlineSnapshot(` "Received array/tuple with the following failures: @@ -230,7 +223,6 @@ describe('union()', () => { ]); expect(() => { - // @ts-expect-error Invalid type objectUnion.validate({ foo: true }); }).toThrowErrorMatchingInlineSnapshot(` "Received object/shape with the following failures: @@ -328,7 +320,6 @@ describe('union()', () => { ]); expect(() => { - // @ts-expect-error Invalid type mixedUnion.validate({ unknown: true }); }).toThrowErrorMatchingInlineSnapshot(` "Received object/shape with the following failures: @@ -337,7 +328,6 @@ describe('union()', () => { `); expect(() => { - // @ts-expect-error Invalid type mixedUnion.validate({ foo: 123 }); }).toThrowErrorMatchingInlineSnapshot(` "Received object/shape with the following failures: @@ -347,7 +337,6 @@ describe('union()', () => { `); expect(() => { - // @ts-expect-error Invalid type mixedUnion.validate({ foo: 'abc', bar: 'abc', baz: 123 }); }).toThrowErrorMatchingInlineSnapshot(` "Received object/shape with the following failures: @@ -358,7 +347,6 @@ describe('union()', () => { `); expect(() => { - // @ts-expect-error Invalid type mixedUnion.validate({ foo: 'abc', bar: 123 }); }).not.toThrow(); @@ -378,7 +366,6 @@ describe('union()', () => { ]); expect(shapesUnion.validate({})).toEqual({}); - // @ts-expect-error Mixed types expect(shapesUnion.validate({ foo: 'foo' })).toEqual({ foo: 'foo', bar: 0, @@ -399,7 +386,6 @@ describe('union()', () => { ]); expect(arrayShapesUnion.validate([])).toEqual([]); - // @ts-expect-error Partial types are allowed? expect(arrayShapesUnion.validate([{ foo: 'foo' }, { bar: 123 }, { baz: true }])).toEqual([ { foo: 'foo',