import createValidator = require('../') /** Static assertion that `value` has type `T` */ // Disable tslint here b/c the generic is used to let us do a type coercion and // validate that coercion works for the type value "passed into" the function. // tslint:disable-next-line:no-unnecessary-generics function assertType(value: T): void {} const input = null as unknown const nullValidator = createValidator({ type: 'null' }) assertType<{ type: 'null' }>(nullValidator.toJSON()) if (nullValidator(input)) { assertType(input) } assertType(nullValidator.errors) assertType(nullValidator.errors[0]) assertType(nullValidator.errors[0].field) assertType(nullValidator.errors[0].message) assertType(nullValidator.errors[0].type) assertType(nullValidator.errors[0].value) const numberValidator = createValidator({ type: 'number' }) assertType<{ type: 'number' }>(numberValidator.toJSON()) if (numberValidator(input)) { assertType(input) } const stringValidator = createValidator({ type: 'string' }) assertType<{ type: 'string' }>(stringValidator.toJSON()) if (stringValidator(input)) { assertType(input) } const personValidator = createValidator({ type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' }, }, required: [ 'name' ] }) if (personValidator(input)) { assertType(input.name) if (typeof input.age !== 'undefined') assertType(input.age) if (typeof input.age !== 'number') assertType(input.age) } const namesValidator = createValidator({ type: 'array', items: { type: 'string' } }) if (namesValidator(input)) { assertType(input.length) assertType(input[0]) } const boxValidator = createValidator({ type: 'object', properties: { name: { type: 'string' }, items: { type: 'array', items: { type: 'boolean' } }, }, required: [ 'name', 'items', ] }) if (boxValidator(input)) { assertType(input.name) assertType(input.items.length) assertType(input.items[0]) } const matrixValidator = createValidator({ type: 'array', items: { type: 'array', items: { type: 'number' } } }) if (matrixValidator(input)) { assertType(input[0][0]) } const userValidator = createValidator({ type: 'object', properties: { name: { type: 'string' }, items: { type: 'array', items: { type: 'string' } }, }, required: [ 'name', 'items', ] }) if (userValidator(input)) { assertType(input.name) assertType(input.items.length) assertType(input.items[0]) } const user2Validator = createValidator({ type: 'object', properties: { name: { type: 'object', properties: { first: { type: 'string' }, last: { type: 'string' }, }, required: [ 'last' as 'last' ] }, items: { type: 'array', items: { type: 'string' }, } }, required: [ 'name' ] }) if (user2Validator(input)) { assertType<{ first: string | undefined, last: string }>(input.name) if (typeof input.name.first !== 'undefined') assertType(input.name.first) if (typeof input.name.first !== 'string') assertType(input.name.first) assertType(input.name.last) if (input.items !== undefined) { assertType(input.items.length) assertType(input.items[0]) } } const booleanValidator = createValidator({ enum: [true, false] }) if (booleanValidator(input)) { assertType(input) } const specificValuesValidator = createValidator({ enum: [ true as true, 1000 as 1000, 'XX' as 'XX' ] }) if (specificValuesValidator(input)) { if (input !== true && input !== 1000) assertType<'XX'>(input) if (input !== 1000 && input !== 'XX') assertType(input) if (input !== 'XX' && input !== true) assertType<1000>(input) } const metricValidator = createValidator({ type: 'object', properties: { name: { type: 'string', enum: ['page-view' as 'page-view'] }, page: { type: 'string', minLength: 0 } }, required: [ 'name', 'page' ] }) if (metricValidator(input)) { assertType<'page-view'>(input.name) assertType(input.page) } const noRequiredFieldsValidator = createValidator({ type: 'object', properties: { a: { type: 'string' }, b: { type: 'string' }, c: { type: 'string' } } }) if (noRequiredFieldsValidator(input)) { if (typeof input.a !== 'string') assertType(input.a) if (typeof input.b !== 'string') assertType(input.b) if (typeof input.c !== 'string') assertType(input.c) if (typeof input.a !== 'undefined') assertType(input.a) if (typeof input.b !== 'undefined') assertType(input.b) if (typeof input.c !== 'undefined') assertType(input.c) } const signupValidator = createValidator({ type: 'object', properties: { email: { type: 'string' }, paymentInformation: { type: 'object', properties: { plan: { type: 'string' }, token: { type: 'string' } }, required: [ 'plan' as 'plan', 'token' as 'token' ] } }, required: [ 'paymentInformation' ] }) if (signupValidator(input)) { if (typeof input.email !== 'string') assertType(input.email) if (typeof input.email !== 'undefined') assertType(input.email) assertType(input.paymentInformation.plan) assertType(input.paymentInformation.token) } const animalValidator = createValidator({ oneOf: [ { type: 'object', properties: { type: { enum: ['cat' as 'cat'] }, name: { type: 'string' } }, required: [ 'type', 'name' ] }, { type: 'object', properties: { type: { enum: ['dog' as 'dog'] }, name: { type: 'string' } }, required: [ 'type', 'name' ] } ] }) if (animalValidator(input)) { if (input.type !== 'cat') assertType<'dog'>(input.type) if (input.type !== 'dog') assertType<'cat'>(input.type) assertType(input.name) } const shapeValidator = createValidator({ oneOf: [ { type: 'object', properties: { kind: { enum: ['triangle' as 'triangle'] } }, required: ['kind'] }, { type: 'object', properties: { kind: { enum: ['rectangle' as 'rectangle'] } }, required: ['kind'] }, { type: 'object', properties: { kind: { enum: ['circle' as 'circle'] } }, required: ['kind'] }, ] }) if (shapeValidator(input)) { if (input.kind !== 'triangle' && input.kind !== 'rectangle') assertType<'circle'>(input.kind) if (input.kind !== 'rectangle' && input.kind !== 'circle') assertType<'triangle'>(input.kind) if (input.kind !== 'circle' && input.kind !== 'triangle') assertType<'rectangle'>(input.kind) } const foobar = createValidator({ oneOf: [ { type: 'object', properties: { a: { type: 'string' } }, required: ['a'] }, { type: 'object', properties: { b: { type: 'number' } }, required: ['b'] }, { type: 'object', properties: { c: { type: 'boolean' } }, required: ['c'] }, { type: 'object', properties: { d: { type: 'null' } }, required: ['d'] }, ] }) if (foobar(input)) { if ('a' in input) assertType(input.a) if ('b' in input) assertType(input.b) if ('c' in input) assertType(input.c) if ('d' in input) assertType(input.d) } const stringOrNullValidator = createValidator({ oneOf: [ { type: 'string' }, { type: 'null' } ] }) if (stringOrNullValidator(input)) { if (typeof input !== 'object') assertType(input) if (typeof input !== 'string') assertType(input) } const primitiveValidator = createValidator({ oneOf: [ { type: 'string' }, { type: 'number' }, { type: 'boolean' } ] }) if (primitiveValidator(input)) { if (typeof input !== 'string' && typeof input !== 'number') assertType(input) if (typeof input !== 'number' && typeof input !== 'boolean') assertType(input) if (typeof input !== 'boolean' && typeof input !== 'string') assertType(input) } const overengineeredColorValidator = createValidator({ oneOf: [ { enum: ['red' as 'red', 'pink' as 'pink'] }, { enum: ['green' as 'green', 'olive' as 'olive'] }, { enum: ['blue' as 'blue', 'teal' as 'teal'] }, { enum: ['yellow' as 'yellow', 'cream' as 'cream'] } ] }) if (overengineeredColorValidator(input)) { if (input !== 'red' && input !== 'pink' && input !== 'green' && input !== 'olive' && input !== 'blue' && input !== 'teal' && input !== 'yellow') assertType<'cream'>(input) if (input !== 'pink' && input !== 'green' && input !== 'olive' && input !== 'blue' && input !== 'teal' && input !== 'yellow' && input !== 'cream') assertType<'red'>(input) if (input !== 'green' && input !== 'olive' && input !== 'blue' && input !== 'teal' && input !== 'yellow' && input !== 'cream' && input !== 'red') assertType<'pink'>(input) if (input !== 'olive' && input !== 'blue' && input !== 'teal' && input !== 'yellow' && input !== 'cream' && input !== 'red' && input !== 'pink') assertType<'green'>(input) if (input !== 'blue' && input !== 'teal' && input !== 'yellow' && input !== 'cream' && input !== 'red' && input !== 'pink' && input !== 'green') assertType<'olive'>(input) if (input !== 'teal' && input !== 'yellow' && input !== 'cream' && input !== 'red' && input !== 'pink' && input !== 'green' && input !== 'olive') assertType<'blue'>(input) if (input !== 'yellow' && input !== 'cream' && input !== 'red' && input !== 'pink' && input !== 'green' && input !== 'olive' && input !== 'blue') assertType<'teal'>(input) if (input !== 'cream' && input !== 'red' && input !== 'pink' && input !== 'green' && input !== 'olive' && input !== 'blue' && input !== 'teal') assertType<'yellow'>(input) } const nullableStringValidator = createValidator({ type: ['string', 'null'] }) if (nullableStringValidator(input)) { if (typeof input !== 'object') assertType(input) if (typeof input !== 'string') assertType(input) } const nullableNameValidator = createValidator({ type: 'object', properties: { name: { type: ['string', 'null'] } }, required: [ 'name' ] }) if (nullableNameValidator(input)) { if (typeof input.name !== 'object') assertType(input.name) if (typeof input.name !== 'string') assertType(input.name) } const nullableInventoryValidator = createValidator({ type: 'object', properties: { inventory: { type: ['array', 'null'], items: { type: 'string' } } }, required: [ 'inventory' ] }) if (nullableInventoryValidator(input)) { if (input.inventory === null) assertType(input.inventory) if (input.inventory !== null) assertType(input.inventory) } const nullableParentValidator = createValidator({ type: 'object', properties: { parent: { type: ['object', 'null'], properties: { name: { type: 'string' } }, required: [ 'name' as 'name' ] } }, required: [ 'parent' ] }) if (nullableParentValidator(input)) { if (input.parent === null) assertType(input.parent) if (input.parent !== null) assertType(input.parent.name) }