{"id":22311616,"url":"https://github.com/ludbek/validatex","last_synced_at":"2025-07-29T08:32:25.749Z","repository":{"id":10755884,"uuid":"66232226","full_name":"ludbek/validatex","owner":"ludbek","description":"A simple yet powerful data validator for javascript.","archived":false,"fork":false,"pushed_at":"2023-01-07T02:04:06.000Z","size":1130,"stargazers_count":12,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-19T22:27:01.476Z","etag":null,"topics":["async","data","javascript","schema","validator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ludbek.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-22T02:10:29.000Z","updated_at":"2022-11-20T22:28:42.000Z","dependencies_parsed_at":"2023-01-13T16:08:04.937Z","dependency_job_id":null,"html_url":"https://github.com/ludbek/validatex","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/ludbek/validatex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ludbek%2Fvalidatex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ludbek%2Fvalidatex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ludbek%2Fvalidatex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ludbek%2Fvalidatex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ludbek","download_url":"https://codeload.github.com/ludbek/validatex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ludbek%2Fvalidatex/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267653256,"owners_count":24122168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","data","javascript","schema","validator"],"created_at":"2024-12-03T21:25:36.051Z","updated_at":"2025-07-29T08:32:25.442Z","avatar_url":"https://github.com/ludbek.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](./media/ValidateX.png)\n![](./media/made-with-typescript.svg)\n![](https://img.shields.io/github/last-commit/ludbek/validatex?color=blue\u0026style=flat-square) ![](https://img.shields.io/github/v/release/ludbek/validatex)\n\n**A simple yet powerful JavaScript/TypeScript data validator.**\n___\n**Table of Contents**\n\n* [v1.x doc](#v1x-dochttpsgithubcomludbekvalidatextreev102)\n* [Migration from v1.x to v2.x](#migration-from-v1x-to-v2x)\n* [Installation](#installation)\n* [Usage](#usage)\n* [Key Features](#key-features)\n* [Kitchen Sink](#kitchen-sink)\n* [Core concepts](#core-concepts)\n  * [Decoder](#decoder)\n    * [Without any option](#without-any-option)\n    * [With DecoderFullOptions](#with-decoderfulloptions)\n  * [Validator](#validator)\n  * [Static type inference](#static-type-inference)\n* [Decoders](#decoders)\n  * [String](#string)\n    * [DecoderOption](#decoderoption)\n    * [Validate](#validate)\n    * [Custom error message](#custom-error-message)\n    * [Validators for String](#validators-for-string)\n      * [minlength](#minlength)\n      * [maxlength](#maxlength)\n      * [email](#email)\n      * [length](#length)\n      * [pattern](#pattern)\n    * [Number](#number)\n      * [Validators for Number](#validators-for-number)\n        * [min](#min)\n        * [max](#max)\n    * [Boolean](#boolean)\n      * [Validators for Boolean](#validators-for-boolean)\n        * [isTrue](#istrue)\n        * [isFalse](#isfalse)\n    * [Date](#date)\n      * [Validators for Date](#validators-for-date)\n        * [minDate](#mindate)\n        * [maxDate](#maxdate)\n  * [Literal](#literal)\n  * [Object](#object)\n  * [Partial](#partial)\n  * [Array](#array)\n  * [Enum](#enum)\n  * [Union](#union)\n___\n## [v1.x doc](https://github.com/ludbek/validatex/tree/v1.0.2)\n\n## Migration from v1.x to v2.x\n___\n\n## Installation\nThis should be installed as one of your project dependencies :\n```bash\n  npm -i validatex\n```\nor\n```bash\n  yarn add validatex\n```\n___\n## Usage\nValidateX aims on providing users with decoders and validators to identify the type of the value and validate the value simultaneously. Along with the decoders and validators that validatex provides, you can create custom decoders/validators.\n___\n\n## Key Features\n- Functions as decoders/validators\n- Supports Typescript\n- Static type inference\n- Easy to extend\n- Easy to create custom decoders/validators\n\n___\n\n## Kitchen Sink\n```typescript\nimport v, { Typeof } from 'validatex'\n\nconst userSchema = v.array(\n  v.object({\n    name: v.string(v.minlenth(1)),\n    mobile: v.toggle(v.number(v.max(9999999999))),\n    address: v.partial({\n      postcode: v.number(),\n      street1: v.string(v.minlenth(1)),\n      street2: v.toggle(v.string()),\n    }),\n  }),\n);\n\ntype UserSchema = Typeof\u003ctypeof userSchema\u003e\n// Runtime type\n//type UserSchema = {\n//    mobile?: number | undefined;\n//    name: string;\n//    address: {\n//        street2: string;\n//        postcode?: number | undefined;\n//        street1?: string | undefined;\n//    };\n//}[]\n\n// if a valid data is given to the schema it returns it back\nconst value1 = [\n  {\n    name: 'foo',\n    mobile: 1234567890,\n    address: {\n      postcode: 1,\n      street1: 'street 1',\n      street2: 'street 2',\n    },\n  },\n];\nexpect(userSchema(value1)).toEqual(value1);\n\n// if an invalid data is given to the schema it throws an error\nconst value2 = [\n  {\n    name: 'foo',\n    mobile: 1234567890,\n    address: {\n      postcode: 1,\n      street1: 'street 1',\n      street2: 'street 2',\n    },\n  },\n  {\n    address: { street1: 'street 1' },\n  },\n];\n\n// the root of the schema is an array, so is the root of the error\nconst expectedError = JSON.stringify([\n  {\n    \"index\":1,\n    \"error\": {\n      \"name\":\"Expected string but got undefined.\",\n      \"address\": {\n        \"street2\":\"Expected string but got undefined.\"\n      }\n    }\n  }\n]);\nexpect(() =\u003e userSchema(userSchema, value2).toThrow(expectedError);\n```\n___\n\n## Core concepts\n#### Decoder\nDecoder is a function that parses unkown value, validates it and returns a known value. A decoder has the following signature.\n\n```typescript\n(val: unknown, context?: Context | undefined) =\u003e T\n```\n\n[//]: \u003c\u003e (Context should be documented here.)\n**Context**\n\n```typescript\ntype Context = {\n  key?: string | undefined;\n  raw?: Record\u003cstring, any\u003e;\n  index?: number | undefined;\n  schema?: any;\n}\n```\n\n##### Without any option\n```typescript\nconst defaultErrorMsg = 'Not a string';\nconst str = decoder\u003cstring, unknown\u003e({\n  typeGuard: (val: unknown): val is string =\u003e typeof val === 'string',\n  getDefaultErrorMsg: () =\u003e defaultErrorMsg,\n  defaultParser: identity,\n});\n\nconst nameSchema = str();\nexpect(nameSchema('foo')).toEqual('foo');\nexpect(nameSchema.bind(nameSchema, 1)).toThrow(defaultErrorMsg);\n```\n\n##### With DecoderFullOptions\n```typescript\nconst defaultErrorMsg = 'Not a string';\nconst customErrorMsg = 'It should be a string.';\nconst customValidationErrorMsg = \"must not contain '-'.\";\nconst str = decoder\u003cstring, unknown\u003e({\n  typeGuard: (val: unknown): val is string =\u003e typeof val === 'string',\n  getDefaultErrorMsg: () =\u003e defaultErrorMsg,\n  defaultParser: identity,\n});\nconst alphaNumSchema = str({\n  parse(val) {\n    if (typeof val === 'string' || typeof val === 'number') return `${val}`;\n    return val;\n  },\n  validate(val, { key } = { key: undefined }) {\n    if (val.includes('-')) return `${key} ${customValidationErrorMsg}`;\n  },\n  errorMsg: customErrorMsg,\n});\nexpect(alphaNumSchema('valid string')).toEqual('valid string');\n// it parses\nexpect(alphaNumSchema(1)).toEqual('1');\n// it respects custom error msg\nexpect(alphaNumSchema.bind(alphaNumSchema, true)).toThrow(customErrorMsg);\n// it respects custom validator\nexpect(\n  alphaNumSchema.bind(alphaNumSchema, 'hello-there', { key: 'akey' }),\n).toThrow(customValidationErrorMsg);\n\n// it respects getErrorMsg\nconst schema = str({\n  getErrorMsg: (val, { key } = { key: undefined }) =\u003e {\n    return `${key} must not be ${val}`;\n  },\n});\nexpect(schema.bind(schema, 1, { key: 'akey' })).toThrow(\n  'akey must not be 1',\n);\n\n// it accepts an array of validators\nconst schemaB = str({ validate: [isSingleWord, max5] });\nexpect(schemaB.bind(schemaB, 'kathmandu')).toThrow(maxError);\nexpect(schemaB.bind(schemaB, 'new road')).toThrow(singleWordError);\nexpect(schemaB('abc')).toEqual('abc');\n```\n\n[//]: \u003c\u003e (Compose complex decoders should be documented here.)\n\n#### Validator\nValidator is a function that validates a known value as its name suggests . It returns an error if a value is invalid else returns nothing. A decoder uses 1 or many validators to validate a known value.\n\n```typescript\n(val: T, context?: Context | undefined) =\u003e string | Record\u003cstring, string\u003e | undefined\n```\n\n#### Static type inference\n```typescript\nimport v, { TypeOf } from 'validatex'\n\nconst loginSchema = v.object({\n  username: v.string(),\n  password: v.string()\n})\n\ntype LoginSchema = TypeOf\u003ctypeof loginSchema\u003e\n// type LoginSchema = {\n//     username: string;\n//     password: string;\n// }\n```\n___\n\n##  Decoders\n### String\nThe **string** decoder parses unknown value, validates it and returns an error or a string value on the basis of the validation.\n\nThe signature of string decoder looks like:\n```typescript\n(options?: DecoderOption\u003cstring\u003e) =\u003e (val: unknown, context?: Context | undefined) =\u003e string\n```\n```typescript\nconst name = v.string()\n```\n\n##### DecoderOption\n```typescript\ntype DecoderOption\u003cT\u003e =\n  | Validator\u003cT\u003e\n  | Validator\u003cT\u003e[]\n  | CustomErrorMsg\n  | DecoderFullOption\u003cT\u003e;\n```\n\n##### Validate\n\n```typescript\nfunction alphaNumeric(val: string) {\n  return /[a-zA-Z][\\da-zA-Z]+/.test(val) ? undefined : 'Must be alpha numeric.';\n}\n\nconst username = v.string(alphaNumeric);\nexpect(username('user1')).toEqual('user1');\n// value validation\nexpect(() =\u003e username('123')).toThrow('Must be alpha numeric.');\n```\n\n##### Custom error message\n```typescript\nconst customErrMsg = \"This is a custom error message\";\n\nconst username = v.string(customErrMsg);\n\nexpect(username.bind(username, 1)).toThrow(customErrorMsg);\n```\n\n#### Validators for String\n\n##### minlength\nThe **minlength()** validates the minimum length of textual data. It takes two parameters, *size* and *customError*.\n\n```typescript\nminLength(size, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *size* | number | It is the minimum length of textual data. It accepts a number. |\n| *customError* | string | It is the customized error. If a customized error isn't passed into the validator then it returns default error message. |\n\n\n\n```typescript\n// Invalid value\nexpect(minlength(5)(\"suku\")).toEqual(`Should be at least 5 characters long`);\n// Valid value\nexpect(minlength(5)(\"summit\")).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(minlength(6, errorMsg)(\"suku\")).toEqual(errorMsg);\n```\n\n##### maxlength\nThe **maxlength()** validates the minimum length of textual data. It takes two parameters, *size* and *customError*.\n\n```typescript\nmaxLength(size, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *size* | number | It is the maximum length of textual data. It accepts a number. |\n\n\n\n```typescript\n// Invalid value\nexpect(maxlength(3)(\"suku\")).toEqual(`Should be no longer than ${len} characters`.);\n// Valid value\nexpect(maxlength(6)(\"summit\")).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(maxlength(3, errorMsg)(\"suku\")).toEqual(errorMsg);\n```\n\n##### email\nThe **email** validator checks if a value is a valid email or not. It only takes *customError* as a parameter.\n\n```typescript\nmaxLength(customError?)\n```\n\n```typescript\n// Invalid value\nexpect(email()('aninvalid.email')).toEqual('The email is not valid');\n// Valid value\nexpect(email()('someone@somewhere.com')).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(email(errorMsg)('aninvalid.email')).toEqual(errorMsg);\n```\n\n##### length\nThe **length** validator validates the exact length of the textual data. The two parameters of this validator are : *size* and *customError*.\n\n```typescript\nlength(size, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *size* | number | It represents the exact length of the textual data. |\n\n\n```typescript\n// Invalid value\nconst expectedError = `Should be 5 characters long`;\nexpect(length(5)('1234')).toEqual(expectedError);expect(length(5)('1234')).toEqual(expectedError);\n// Valid value\nexpect(length(1)('1')).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(length(5, errorMsg)('1')).toEqual(errorMsg);\n```\n\n##### pattern\nThe **pattern** validator checks if a value matches a specific pattern. It takes two parameters: *regex* and *customError*.\n```typescript\npattern(regex, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *regex* | regular expression | A pattern that entered data needs to follow. |\n\n```typescript\n// Invalid value\nexpect(pattern(/^[a-b]/)('z')).toEqual(`The value 'z' doen't match the pattern /^[a-b]/`);\n// Valid value\nexpect(pattern(/^[a-z0-9]*$/)('12ba')).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(pattern(/^[a-z0-9]*$/, errorMsg)('abc_123')).toEqual(errorMsg);\n```\n\n### Number\nThe **number** decoder takes an unknown value, validates it and returns an error or a number depending on the outcome of the validation.\n```typescript\n(options?: DecoderOption\u003cnumber\u003e) =\u003e (val: unknown, context?: Context | undefined) =\u003e number\n```\n\n```typescript\nconst age = v.number();\n\nexpect(age(20)).toEqual(20);\n// validation of value except number\nexpect(() =\u003e age(\"twenty\")).toThrow('Expected number but got string.');\n```\n\n#### Validators for Number\n\n##### min\nThe **min** validator checks whether a value is greater than the minimum value specified. The two parameters of the validators are: *number* and *customError*.\n\n```typescript\nmin(number, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *number* | number | Minimum value that entered data needs to be greater than. |\n\n\n```typescript\n// Invalid value\nexpect(min(15)(12)).toEqual(`Value 12 should be greater than 15`);\n// Valid value\nexpect(min(15)(17)).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(min(6, errorMsg)(5)).toEqual(errorMsg);\n```\n\n##### max\nThe **max** validator checks whether a value is smaller than the maximum value specified. The two parameters of the validators are: *number* and *customError*.\n\n```typescript\nmax(number, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *number* | number | Maximum value that entered data needs to be smaller than. |\n\n```typescript\n// Invalid value\nexpect(max(12)(15)).toEqual(`Value 15 should be smaller than 12`);\n// Valid value\nexpect(max(6)(4)).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = 'Custom error.';\nexpect(max(3, errorMsg)(5)).toEqual(errorMsg);\n```\n\n### Boolean\nThe **boolean** decoder takes an unknown value, validates it and returns an error or a number depending on the outcome of the validation.\n```typescript\n(options?: DecoderOption\u003cboolean\u003e) =\u003e (val: unknown, context?: Context | undefined) =\u003e boolean\n```\n\n```typescript\nconst married = v.boolean();\n\nexpect(married(true)).toEqual(true);\n// validation of value except boolean\nexpect(() =\u003e married(1)).toThrow('Expected boolean but got number.');\n```\n#### Validators for Boolean\n\n##### isTrue\nThe **isTrue** validator checks whether a boolean value is true. The only parameter of the validator is: *customError*.\n\n```typescript\nisTrue(customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *customError* | string | It is the customized error. If a customized error isn't passed into the validator then it returns default error message. |\n\n\n```typescript\n// false value\nconst expectedError = `Expected true but got false`;\nexpect(isTrue()(false)).toEqual(expectedError);\n// true value\nexpect(isTrue()(true)).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = `Custom error message`;\nexpect(isTrue(errorMsg)(false)).toEqual(errorMsg);\n```\n\n##### isFalse\nThe **isFalse** validator checks whether a boolean value is false. The only parameter of the validator is: *customError*.\n\n```typescript\nisFalse(customError?)\n```\n\n```typescript\n// true value\nconst expectedError = `Expected false but got true`;\nexpect(isFalse()(true)).toEqual(expectedError);\n// false value\nexpect(isFalse()(false)).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = `Custom error message`;\nexpect(isFalse(errorMsg)(true)).toEqual(errorMsg);\n```\n\n### Date\nThe **date** decoder takes an unknown value, validates if it and returns an error or a Date depending on the outcome of the validation.\n```typescript\n(options?: DecoderOption\u003cDate\u003e) =\u003e (val: unknown, context?: Context | undefined) =\u003e Date\n```\n If the unknown value is string, it parses the string to a date object. The decoder will return a date object only if the input is a valid date else return an error that says \"Expected Date but got object.\"\n\n```typescript\nconst dateOfBirth = v.date();\n\n// Both the \"/\" or \"-\" symbols work well\nexpect(dateOfBirth(new Date(\"2001/04/05\"))).toEqual(new Date(\"2001/04/05\"));\n// Parses string to a date object.\nexpect(dateOfBirth(\"2001-04-05\")).toEqual(new Date(\"2001-04-05\"));\n\n// Invalid date validation\nexpect(() =\u003e dateOfBirth(\"2001-15-32\")).toThrow(\"Expected Date but got object.\");\n// Validation of value except Date object and string\nexpect(() =\u003e dateOfBirth(2001)).toThrow(\"Expected Date but got number.\");\n```\n\n#### Validators for Date\n\n##### minDate\nThe **minDate** validator set the minimum date and checks whether the entered date comes after the minimum date. It takes two parameters: *date* and *customError*.\n\n```typescript\nminDate(date, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *date* | date object | Minimum date that can be entered. |\n\n```typescript\n// Invalid value\nconst expectedError = `The entered date must come after Mon Apr 05 2021`;\nexpect(minDate(new Date(\"2021/4/5\"))(new Date(\"2021/3/4\"))).toEqual(expectedError);\n// Valid value\nexpect(minDate(new Date(\"2021/4/5\"))(new Date(\"2021/4/6\"))).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = `The date entered doesn't exist.`;\nexpect(minDate(new Date(\"2021/4/5\"), errorMsg)(new Date(\"2020/4/6\"))).toEqual(errorMsg);\n```\n\n##### maxDate\nThe **maxDate** validator set the maximum date and checks whether the entered date comes before the maximum date. It takes two parameters: *date* and *customError*.\n\n```typescript\nmaxDate(date, customError?)\n```\n\n| Name | Type | Description |\n| ----------- | ----------- | ----------- |\n| *date* | date object | Maximum date that can be entered. |\n\n```typescript\n// Invalid value\nconst expectedError = `The entered date must come before Mon Apr 05 2021`;\nexpect(maxDate(new Date(\"2021/4/5\"))(new Date(\"2021/6/4\"))).toEqual(expectedError);\n// Valid value\nexpect(maxDate(new Date(\"2021/4/5\"))(new Date(\"2020/5/6\"))).toEqual(undefined);\n\n// Passing customError\nconst errorMsg = `The date entered doesn't exist.`;\nexpect(maxDate(new Date(\"2021/4/5\"), errorMsg)(new Date(\"2022/4/6\"))).toEqual(errorMsg);\n```\n\n### Literal\nThe **literal** decoder parses an any value, validates if it and returns an error or a Premitive value depending on the outcome of the validation. \n\nThe type **Premitive** looks like :\n```typescript\ntype Premitive = string | number | boolean | null | undefined;\n```\n\n**Signature of literal decoder**\n```typescript\n(val: T, options?: DecoderOption\u003cPremitive\u003e) =\u003e (val: any, context?: Context | undefined) =\u003e Premitive\n```\n\n```typescript\nconst apple = v.literal('apple');\n\nexpect(apple('apple')).toEqual('apple');\nexpect(() =\u003e apple('banana')).toThrow(`Expected 'apple', but got 'banana'.`);\n```\n\n### Object\nThe **object** decoder parses any value, validates if it and returns an error or a Schema value depending on the outcome of the validation.\n\n**Schema**\n```typescript\ntype Schema = Record\u003cstring, Decoder | Switch\u003cany\u003e\u003e;\n```\n**Signature of object decoder**\n```typescript\n(schema: T, option?: ObjectOption) =\u003e (rawData: any, context?: Context) =\u003e Schema\n```\n\n\n```typescript\nconst userSchema = v.object({\n  name: string(),\n  address: string()\n});\n\nconst val = { name: 'foo', address: 'bar' };\nexpect(userSchema(val)).toEqual(val);\n\nconst expectedError = JSON.stringify({\n  name: 'Expected string but got undefined.',\n  address: 'Expected string but got undefined.',\n});\n// invalid value\nexpect(() =\u003e userSchema({})).toThrow(expectedError);\n// non-object validation\nexpect(userSchema.bind(userSchema, 1)).toThrow(expectedError)\n\n//unknown field validation\nconst data = {\n  username: 'a username',\n  password: 'a password',\n  unknownField1: 'unknown field 1',\n  unknownField2: 'unknown field 2',\n};\nexpect(userSchema.bind(userSchema, data)).toThrow(`{\"unknownField1\":\"Unknown field.\",\"unknownField2\":\"Unknown field.\"}`)\n```\n\n### Partial\n\n```typescript\n(schema: T, option?: PartialOption) =\u003e (val: any, context?: Context) =\u003e Schema\n```\n```typescript\n// making all fields optional\nconst userSchema = partial({\nusername: string(),\npassword: string(),\n});\nexpect(userSchema({})).toEqual({});\n\n// working with toggle\nconst userSchema = partial({\n  username: string(),\n  password: toggle(string()),\n});\nexpect(userSchema.bind(userSchema, {})).toThrow('');\n```\n\n### Array\nThe **array** decoder parses any value, validates if its value is of type Arrary and returns an error or an Array value depending on the outcome of the validation.\n\n**Decoder**\n```typescript\ntype Decoder = (value: any, context?: Context) =\u003e any;\n```\n**Signature of object decoder**\n```typescript\n(schema: T, option?: ArrayOptions\u003e) =\u003e (val: any, context?: Context) =\u003e Array\n```\n\n```typescript\nconst namesSchema = array(string());\nconst value = ['foo', 'bar'];\n// valid value\nexpect(namesSchema(value)).toEqual(value);\n\nconst value = [1, undefined];\nconst expectedError = [\n  { index: 0, error: 'Expected string but got number.' },\n  { index: 1, error: 'Expected string but got undefined.' },\n];\n// invalid value\nexpect(namesSchema.bind(namesSchema, value)).toThrow(\n  JSON.stringify(expectedError),\n);\n\nconst expectedError = [\n  { index: 0, error: 'Expected string but got undefined.' },\n];\n// Non-array value\nexpect(namesSchema.bind(namesSchema, undefined)).toThrow(\n  JSON.stringify(expectedError),\n);\n\nconst expectedError = [\n  { index: 0, error: 'Expected string but got undefined.' },\n];\n// empty array validation\nexpect(namesSchema.bind(namesSchema, [])).toThrow(\n  JSON.stringify(expectedError),\n);\n\n// custom validation\nconst expectedError = `Only 2 items are allowed`;\nfunction allowOnly2(values: string[]) {\n  if (values.length \u003e 2) return expectedError;\n}\nconst namesSchema = array(string(), allowOnly2);\nexpect(namesSchema.bind(namesSchema, ['a', 'b', 'c', 'd'])).toThrow(\n  expectedError,\n);\n```\n\n### Enum\nThe **enum** decoder parses any value, validates if its value is of type EnumValues and returns an error or a EnumValues value depending on the outcome of the validation.\n```typescript\ntype EnumValues = string | number | boolean;\n```\n**Signature of object decoder**\n```typescript\n(values: [...T], option?: DecoderOption\u003cT\u003e) =\u003e (val: unknown, context?: Context) =\u003e EnumValues\n```\n\n```Typescript\nconst fruits = v.enum(['apple', 'banana']);\n\n// valid value\nconst apple = 'apple';\nexpect(fruits(apple)).toEqual(apple);\n\n// invalid value\nconst expectedError = `Expected one of ['apple', 'banana'] but got 'tomato'.`;\nexpect(() =\u003e fruits('tomato')).toThrow(expectedError);\n```\n\n### Union\n```typescript\n(schemas: T, option?: DecoderOption\u003cK\u003e) =\u003e (val: unknown, context?: Context) =\u003e T\n```\n\n```typescript\nconst alphaNumeric = union([string(), number()]);\n\n// valid values\nexpect(alphaNumeric('a')).toEqual('a');\nexpect(alphaNumeric(1)).toEqual(1);\n\n// invalid value\nexpect(() =\u003e alphaNumeric(true)).toThrow(\n  'The value did not match any of the given schemas.',\n);\n```\n___\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fludbek%2Fvalidatex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fludbek%2Fvalidatex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fludbek%2Fvalidatex/lists"}