{"id":22521803,"url":"https://github.com/ncpa0/dilswer","last_synced_at":"2026-02-17T18:05:20.390Z","repository":{"id":63177929,"uuid":"426594546","full_name":"ncpa0/Dilswer","owner":"ncpa0","description":"Blazingly fast data validation library with TypeScript integration.","archived":false,"fork":false,"pushed_at":"2025-03-31T12:59:37.000Z","size":3769,"stargazers_count":1,"open_issues_count":7,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-09T04:38:11.855Z","etag":null,"topics":["json-schema","typescript","validation","validator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ncpa0.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-11-10T11:23:24.000Z","updated_at":"2025-03-31T12:59:40.000Z","dependencies_parsed_at":"2024-06-21T16:33:16.492Z","dependency_job_id":"9f03c420-bd42-4f4b-aa9b-07f2aebee084","html_url":"https://github.com/ncpa0/Dilswer","commit_stats":null,"previous_names":["ncpa0cpl/dilswer"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/ncpa0/Dilswer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncpa0%2FDilswer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncpa0%2FDilswer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncpa0%2FDilswer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncpa0%2FDilswer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ncpa0","download_url":"https://codeload.github.com/ncpa0/Dilswer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncpa0%2FDilswer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29552265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T17:56:56.811Z","status":"ssl_error","status_checked_at":"2026-02-17T17:56:55.544Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["json-schema","typescript","validation","validator"],"created_at":"2024-12-07T05:13:00.821Z","updated_at":"2026-02-17T18:05:20.374Z","avatar_url":"https://github.com/ncpa0.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dilswer\n\n![GitHub](https://img.shields.io/github/license/ncpa0cpl/Dilswer?style=for-the-badge)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ncpa0cpl/dilswer/test.yml?branch=master\u0026style=for-the-badge)\n[![npm](https://img.shields.io/npm/v/dilswer?style=for-the-badge)](https://www.npmjs.com/package/dilswer)\n![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/Dilswer?style=for-the-badge)\n![GitHub last commit](https://img.shields.io/github/last-commit/ncpa0cpl/Dilswer?style=for-the-badge)\n\nBlazingly fast data validation library with TypeScript integration.\n\n## Table Of Contents\n\n1. [Quick Start](#quick-start)\n   1. [Create type definitions](#create-type-definitions)\n   2. [Create a TypeScript type from a Dilswer definition](#create-a-typescript-type-from-a-dilswer-definition)\n   3. [Create a validation function](#create-a-validation-function)\n   4. [Assertion function](#assertion-function)\n   5. [Standard Schema support](#standard-schema-support)\n2. [Other features](#other-features)\n   1. [Json Schema generation](#json-schema-generation)\n   2. [TypeScript type definition generation](#typescript-type-definition-generation)\n3. [Availabla Type's](#availabla-types)\n   1. [Number](#typenumber)\n   2. [Int](#typeint)\n   3. [String](#typestring)\n   4. [StringNumeral](#typestringnumeral)\n   5. [StringInt](#typestringint)\n   6. [StringMatching](#typestringmatchingregex)\n   7. [Boolean](#typeboolean)\n   8. [Symbol](#typesymbol)\n   9. [Null](#typenull)\n   10. [Undefined](#typeundefined)\n   11. [Function](#typefunction)\n   12. [Unknown](#typeunknown)\n   13. [OneOf](#typeoneoftypes)\n   14. [AllOf](#typealloftypes)\n   15. [Array](#typearraytypes)\n   16. [Record](#typerecordrecordstring-fielddescriptor)\n   17. [Dict](#typedicttypes)\n   18. [Set](#typesettypes)\n   19. [Literal](#typeliteralstring--number--boolean)\n   20. [InstanceOf](#typeinstanceofclass)\n   21. [Enum](#typeenumenum)\n   22. [EnumMember](#typeenummemberenum-member)\n   23. [Recursive](#typerecursivefunction)\n   24. [Custom](#typecustomfunction)\n4. [Utility Functions](#utility-functions)\n   1. [And](#and)\n   2. [Omit](#omit)\n   3. [Pick](#pick)\n   4. [Partial](#partial)\n   5. [Required](#required)\n   6. [Exclude](#exclude)\n5. [Metadata](#metadata)\n   1. [Assign Metadata](#assign-metadata)\n   2. [Read Metadata](#read-metadata)\n   3. [Metadata and JSON Schema's](#metadata-and-json-schemas)\n6. [Parsing](#parsing)\n\n## Quick Start\n\n#### Create type definitions\n\n```ts\n// person-type.ts\nimport { Type } from \"dilswer\";\n\n// Record property types can be defined in a few different ways:\nconst PersonDataType = Type.Record({\n  id: Type.String,\n  name: Type.String,\n  age: { type: Type.Number },\n  email: Type.Option(Type.String),\n  friends: { type: Type.Array(Type.String), required: false },\n});\n\n// A TypeScript equivalent type of the above would be:\n// type Person = {\n//   id: string;\n//   name: string;\n//   age: number;\n//   email?: string;\n//   friends?: string[];\n// };\n```\n\n**NOTE:** the `required` attribute in a RecordOf fields is set to `true` by\ndefault.\n\n#### Create a TypeScript type from a Dilswer definition\n\nIt is possible to infer a TypeScript type from a Dilswer definition:\n\n```ts\nimport { Infer } from \"dilswer\";\nimport { PersonDataType } from \"./person-type.ts\";\n\ntype Person = Infer\u003ctypeof PersonDataType\u003e;\n\n// Result:\n// type Person: {\n//   id: string;\n//   name: string;\n//   age: number;\n//   email?: string;\n//   friends?: string[];\n// }\n```\n\n#### Create a validation function\n\n```ts\nimport { validator } from \"dilswer\";\nimport { PersonDataType } from \"./person-type.ts\";\n\nconst isPerson = validator(PersonDataType);\n\n// Result:\n// const isPerson: (data: unknown) =\u003e data is {\n//     friends?: string[];\n//     id: string;\n//     name: string;\n//     age: number;\n// }\n\nconst person = await axios\n  .get(\"https://my-api.io/get-person/1\")\n  .then((r) =\u003e r.data);\n\nif (isPerson(person)) {\n  console.log(\"Name: \", person.name);\n  // do something with person\n} else {\n  console.error(\"`person` variable is not of expected type.\");\n  // handle the validation failure\n}\n```\n\n##### validation details\n\nif you want to obtain more details about validation failures, validator can be passed a second argument that will change the bahavior of the validate function:\n\n```ts\nimport { validator } from \"dilswer\";\nimport { PersonDataType } from \"./person-type.ts\";\n\nconst isPerson = validator(PersonDataType, { details: true });\n\n// Result:\n// const isPerson: (data: unknown) =\u003e {\n//   success: false;\n//   error: ValidationError;\n// } | {\n//   success: true;\n//   value: {\n//     friends?: string[];\n//     id: string;\n//     name: string;\n//     age: number;\n//   };\n// }\n```\n\n#### Assertion function\n\nAssertion function can change the type of a variable by simply being called:\n\n```ts\nimport { Type, assertType } from \"dilswer\";\n\nfunction foo(value: any) {\n  try {\n    assertType(Type.String, value);\n    value.toUpperCase(); // value is now treated as string by TypeScript\n  } catch (error) {\n    console.error(\"Value is not a string\");\n  }\n}\n```\n\n### Standard Schema support\n\nDilswer can be used with any library that supports the Standard Schema validation, like tRPC, OpenAuth and others.\n\n```ts\nimport { Type } from \"dilswer\";\nimport { initTRPC } from \"@trpc/server\";\n\nconst t = initTRPC.create();\n\nconst router = t.router({\n  greeting: t.procedure\n    .input(Type.Record({\n      name: Type.String,\n    }))\n    .query(async ({ input }) =\u003e {\n      return `Hello, ${input.name}!`;\n    }),\n})\n```\n\nFor the best performance, type schemas passed to the other libraries should get compiled via the `.compile()` method.\nThe compiled schemas do not provide as detailed error messages but are order of magnitude faster.\n\n```ts\nconst router = t.router({\n  greeting: t.procedure\n    .input(\n      Type.Record({\n        name: Type.String,\n      }).compile()\n    )\n    .query(async ({ input }) =\u003e {\n      return `Hello, ${input.name}!`;\n    }),\n})\n```\n\n## Other features\n\n### Json Schema generation\n\nTranslates given Type into a JSON Schema.\n\n```ts\nconst toJsonSchema: (\n  type: AnyType,\n  options: ParseToJsonSchemaOptions = {},\n  include$schemaProperty = true\n) =\u003e JSONSchema6 | undefined;\n```\n\n#### ParseToJsonSchemaOptions\n\n```ts\ntype ParseToJsonSchemaOptions = {\n  /**\n   * Defines how to handle DataTypes that do not have an\n   * equivalent type in JSON Schema. (Set's, undefined, Symbols,\n   * etc.)\n   *\n   * - `throw` (default): Throw an error if an incompatible type is\n   *   encountered.\n   * - `omit`: Omits incompatible properties from the JSON Schema.\n   * - `set-as-any`: Adds the type to the schema without a \"type\"\n   *   property but with a name equivalent to the given\n   *   DataType.\n   */\n  incompatibleTypes?: \"throw\" | \"omit\" | \"set-as-any\";\n  /**\n   * Determines if the schemas generated for Record's should have\n   * additional properties set to `true` or `false`.\n   */\n  additionalProperties?: boolean;\n  /**\n   * Custom Parser's are methods used to parse incompatible\n   * DataTypes to JSON Schema's.\n   *\n   * By default a strategy defined in `incompatibleTypes` is\n   * used, if a method is defined, that method will be used\n   * instead.\n   */\n  customParser?: {\n    Set?: (\n      setItemsSchemas: JSONSchema6[],\n      original: SetType\u003cAnyType[]\u003e,\n      options: ParseToJsonSchemaOptions,\n    ) =\u003e JSONSchema6 | undefined;\n    Custom?: (\n      validateFunction: Custom[\"custom\"],\n      original: Custom,\n      options: ParseToJsonSchemaOptions,\n    ) =\u003e JSONSchema6 | undefined;\n    Undefined?: (\n      dataType: BasicType,\n      options: ParseToJsonSchemaOptions,\n    ) =\u003e JSONSchema6 | undefined;\n    Symbol?: (\n      dataType: BasicType,\n      options: ParseToJsonSchemaOptions,\n    ) =\u003e JSONSchema6 | undefined;\n    Function?: (\n      dataType: BasicType,\n      options: ParseToJsonSchemaOptions,\n    ) =\u003e JSONSchema6 | undefined;\n  };\n};\n```\n\n#### TypeScript type definition generation\n\nTranslates given Type into a TypeScript type definition. This is not very\nuseful at runtime, and is mostly intended for generating type definitions with\nJSDoc comments that can be bundled with libraries.\n\n```ts\nconst toTsType: (\n  dataType: AnyType,\n  options?: Partial\u003cTsParsingOptions\u003e,\n) =\u003e string;\n```\n\n#### TsParsingOptions\n\n```ts\ntype TsParsingOptions = {\n  /**\n   * Defines how to parse the type.\n   *\n   * - `compact` - the type will be parsed into a single type\n   *   definition\n   * - `fully-expanded` - the type will be split into multiple type\n   *   definitions, and the main DataType type definition will\n   *   reference them.\n   * - `named-expanded` - similar to `fully-expanded`, but only the\n   *   types that have titles assigned will be split into\n   *   separate type definitions.\n   *\n   * @default `compact`\n   */\n  mode: TsParsingMode;\n  /**\n   * Defines how to export the generated types.\n   *\n   * - `main` - only the main DataType type will be exported\n   * - `all` - all types generated will be exported\n   * - `named` - only the types with titles will be exported\n   * - `none` - nothing will be exported\n   *\n   * @default `main`\n   */\n  exports: \"main\" | \"named\" | \"all\" | \"none\";\n  /**\n   * Defines whether to generate the type as a declaration or\n   * not.\n   *\n   * The difference is that declaration will generate each type\n   * definition with a `declare` keyword preceding it.\n   *\n   * @default `false`\n   */\n  declaration: boolean;\n  /**\n   * Defines how to handle duplicate names.\n   *\n   * - `error` - will throw an error if a duplicate name is\n   *   encountered\n   * - `rename` - will rename the duplicate type\n   *\n   * @default `error`\n   */\n  onDuplicateName: \"error\" | \"rename\";\n  /**\n   * Some DataType can reference enums or classes, in which case\n   * it's sometimes impossible to generate a valid TypeScript\n   * type for them. By default just the name of that class/enum\n   * will be used, and if that name is not available in the\n   * global scope, TS will resolve it to `any`. This option\n   * allows to define a custom import path for such types.\n   *\n   * @example\n   *   // foo.ts\n   *   export class Foo {}\n   *\n   *   // data-type.ts\n   *   import { Foo } from \"./foo\";\n   *\n   *   export const dt = Type.RecordOf({\n   *     foo: Type.InstanceOf(Foo),\n   *   });\n   *\n   *   // ts-type-generator.ts\n   *   import { dt } from \"./data-type\";\n   *   import { Foo } from \"./foo\";\n   *\n   *   const tsType = toTsType(dt, {\n   *     getExternalTypeImport: (t) =\u003e {\n   *       if (t.instanceOf === Foo) {\n   *         return {\n   *           typeName: \"Foo\",\n   *           path: \"./foo\",\n   *         };\n   *       }\n   *     },\n   *   });\n   *   // tsType:\n   *   //\"\n   *   // import { Foo } from \"./foo\";\n   *   //\n   *   // export type Record1 = {\n   *   //   foo: InstanceType\u003ctypeof Foo\u003e;\n   *   // }\n   *   //\"\n   */\n  getExternalTypeImport?: (\n    type: EnumType | EnumMemberType | InstanceType | CustomType | FunctionType,\n  ) =\u003e ExternalTypeImport | undefined;\n};\n\ntype TsParsingMode = \"compact\" | \"fully-expanded\" | \"named-expanded\";\n\ntype ExternalTypeImport = {\n  /**\n   * Path to the file containing the external type. If the path\n   * is not specified, the import statement will be omitted, so\n   * for the generated declarations to be valid, you will have to\n   * include that yourself or make the specified type available\n   * in the global scope.\n   */\n  path?: string;\n  /**\n   * Name of the type as it is to be used within the generated\n   * declarations.\n   *\n   * If original name is not provided this is also the name of\n   * the imported type.\n   */\n  typeName: string;\n  /**\n   * Name of the type that will be used in the generated import\n   * statement.\n   */\n  originalName?: string;\n  /**\n   * Whether the imported name is a \"value\" or a \"type\". If it is\n   * a \"value\" it will be referenced with a `typeof` keyword.\n   */\n  valueImport?: boolean;\n};\n```\n\n### Availabla Type's\n\n\n#### Type.Number\n\nwill match any number values and translate to the standard `number` type in\nTypeScript.\n\n#### Type.Int\n\nwill match any integer values and translate to the standard `number` type in\nTypeScript. TypeScript does not have any way of distinguishing float and\nintegers therefore both are assigned the same TypeScript type.\n\n#### Type.String\n\nwill match any string values and translate to the standard `string` type in\nTypeScript.\n\n#### Type.StringNumeral\n\nwill match any string containing only numeric values and translate to a\n`` `${number}` `` type in TypeScript. A value successfully validated with\n`StringNumeral` is safe to convert into a number and will never produce a `NaN`\nvalue.\n\n#### Type.StringInt\n\nwill match any string containing only numbers and translate to a\n`` `${number}` `` type in TypeScript. Strings with floating point numbers are\nnot matched by this type. A value successfully validated with `StringInt` is\nsafe to convert into a number and will never produce a `NaN` value.\n\n#### Type.StringMatching(regex)\n\nwill match any string matching the provided regular expression and translate to\na the standard `string` type in TypeScript.\n\n#### Type.Boolean\n\nwill match any `true` and `false` values and translate to the standard `boolean`\ntype in TypeScript.\n\n#### Type.Symbol\n\nwill match any symbolic values and translate to the `symbol` type in TypeScript.\n\n#### Type.Null\n\nwill match only `null` value and translate to the standard `null` type in\nTypeScript.\n\n#### Type.Undefined\n\nwill match only `undefined` value and translate to the standard `undefined` type\nin TypeScript.\n\n#### Type.Function\n\nwill match any function and translate to the `Function` type in TypeScript.\n\n#### Type.Unknown\n\nwill match any value and translate to the `unknown` type in TypeScript.\n\n#### Type.OneOf(...Type's)\n\nwill match any value matching one of the DataType's provided in the arguments\nand translate to an TypeScript union type.\n\nExample\n\n```ts\nconst foo = Type.OneOf(Type.String, Type.Number);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = (string | number)\n```\n\n#### Type.AllOf(...Type's)\n\nwill match values matching every DataType provided and translate to a TypeScript\nintersection of all those DataType's.\n\nMostly useful to intersect multiple RecordOf's.\n\nExample\n\n```ts\nconst foo = Type.Record({ foo: string });\nconst bar = Type.Record({ bar: string });\n\nconst combined = Type.AllOf(foo, bar);\n\ntype T = Infer\u003ctypeof combined\u003e; // type T = { foo: string; bar: string; }\n```\n\n#### Type.Array(...Type's)\n\nwill match any array which contains only values matching any of the DataType's\nprovided in the arguments and translate to the `Array\u003c...\u003e` type in TypeScript.\n\nExample\n\n```ts\nconst foo = Type.Array(Type.String, Type.Number);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = (string | number)[]\n```\n\n#### Type.Record(Record\u003cstring, FieldDescriptor\u003e)\n\nwill match any object which structure matches the key-value pairs of object\nproperties and FieldDescriptor's passed to the argument.\n\nExample\n\n```ts\nconst foo = Type.Record({\n  foo: Type.Boolean,\n  bar: Type.String,\n  baz: { type: Type.Number, required: false },\n  qux: Type.Option(Type.String),\n});\n\ntype T = Infer\u003ctypeof foo\u003e;\n// type T = { foo: boolean, bar: string, baz?: number | undefined; qux?: string | undefined; }\n```\n\n#### Type.Dict(...Type's)\n\nwill match any object which properties match against the provided DataTypes's,\nand translates to a Record type in TypeScript.\n\nExample\n\n```ts\nconst dictOfFunctions = Type.Dict(Type.Function);\n\ntype T = Infer\u003ctypeof dictOfFunctions\u003e; // type T = Record\u003cstring | number, Function\u003e\n```\n\n#### Type.Set(...Type's)\n\nwill match any Set object which contains only values matching any of the\nDataType's provided in the arguments and translate to the `Set\u003c...\u003e` type in\nTypeScript.\n\nExample\n\n```ts\nconst foo = Type.Set(Type.String, Type.Number);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = Set\u003cstring | number\u003e\n```\n\n#### Type.Literal(string | number | boolean)\n\nwill match any value that exactly matches the passed argument and translate to\nthe literal type of that value in TypeScript.\n\nExample's\n\n```ts\nconst foo = Type.Literal(\"some-string-literal\");\n\ntype T0 = GetDataType\u003ctypeof foo\u003e; // type T0 = \"some-string-literal\"\n```\n\n```ts\nconst bar = Type.Literal(123);\n\ntype T1 = GetDataType\u003ctypeof bar\u003e; // type T1 = 123\n```\n\n```ts\nconst baz = Type.Literal(true);\n\ntype T2 = GetDataType\u003ctypeof baz\u003e; // type T2 = true\n```\n\n#### Type.InstanceOf(class)\n\nwill match any value that is an instance of the passed class and translate to\nthe `InstanceType` type of that class in TypeScript.\n\n```ts\nclass FooBar {\n  // ...\n}\n\nconst foo = Type.InstanceOf(FooBar);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = InstanceType\u003ctypeof FooBar\u003e\n```\n\n#### Type.Enum(enum)\n\nwill match any value that belongs to an TypeScript enum and translate to that\nenum type.\n\n```ts\nenum MyEnum {\n  A = \"A\",\n  B = \"B\",\n}\n\nconst foo = Type.Enum(MyEnum);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = MyEnum\n\nconst validate = validator(foo);\n\nvalidate(MyEnum.A); // =\u003e true\nvalidate(MyEnum.B); // =\u003e true\n```\n\n#### Type.EnumMember(enum member)\n\nwill match any value that equals to the specified TypeScript enum member and\ntranslate to that enum member type.\n\n```ts\nenum MyEnum {\n  A = \"VALUE_A\",\n  B = \"VALUE_B\",\n}\n\nconst foo = Type.EnumMember(MyEnum.A);\n\ntype T = Infer\u003ctypeof foo\u003e; // type T = MyEnum.A\n\nconst validate = validator(foo);\n\nvalidate(\"VALUE_A\"); // =\u003e true\nvalidate(MyEnum.A); // =\u003e true\nvalidate(MyEnum.B); // =\u003e false\n```\n\n#### Type.Recursive(Function)\n\nAllows to define types that reference themselves. The function it accepts should\nalways return a valid DataType, which the reference provided to that function\nwill point to.\n\nExample\n\n```ts\nconst Node = Type.Recursive((self) =\u003e\n  Type.Record({\n    tag: Type.String,\n    children: Type.ArrayOf(self),\n  })\n);\n\n// this is equivalent to the following type:\ntype Node = {\n  tag: string;\n  children: Node[];\n};\n```\n\nType definitions given for circular DataTypes via `GetDataType` and validation\nmethods will not however include infinite recursion as they should. (this does\nnot affect the runtime validation) Due to the TypeScript limitations, it's\nimpossible for a inferred type to include a reference to itself, so to get a\nusable type we use some TypeScript magic to create a similar type that is\n4-levels deep. For the above example the actual type you will get will look like\nthis:\n\n```ts\ntype Node = {\n  tag: string;\n  children: Array\u003c{\n    tag: string;\n    children: Array\u003c{\n      tag: string;\n      children: Array\u003c{\n        tag: string;\n        children: Array\u003cany\u003e;\n      }\u003e;\n    }\u003e;\n  }\u003e;\n};\n```\n\nIf you absolutely need to get a type that has infinite recursion, you can use\n[toTsType](#totstype) utility to generate TypeScript code which will meet that\nneed.\n\n#### Type.Custom(Function)\n\nwill test the data with the provided function, provided function should return a\nboolean indicating if the tested value passed the validation, passed function\nshould also have a type definition that looks like this: `(v: any) =\u003e v is T`,\nwhere T is any valid TS type.\n\nExample\n\n```ts\nconst NonEmptyString = Type.Custom(\n  (v: any): v is string =\u003e typeof v === \"string\" \u0026\u0026 v.length \u003e 0\n);\n\ntype T = Infer\u003ctypeof NonEmptyString\u003e; // type T = string\n\nconst validate = validator(NonEmptyString);\n\nvalidate(\"foo\"); // =\u003e true\nvalidate(\"\"); // =\u003e false\n```\n\n### Utility Functions\n\n#### And()\n\n`And()` utility function can combine two Record Type Definitions into one. If\nany of the properties between the two combined Type Defs have the same key-name,\nthe definition of the second one takes priority.\n\n```ts\nconst typeDefOne = Type.Record({\n  foo: Type.Number,\n  bar: Type.Number,\n});\n\nconst typeDefTwo = Type.Record({\n  bar: Type.Array(Type.String),\n  baz: Type.Boolean,\n});\n\nconst typeDefSum = And(typeDefOne, typeDefTwo);\n// typeDefSum = {\n//    foo: number;\n//    bar: string[];\n//    baz: boolean;\n// }\n```\n\n#### Omit()\n\n`Omit()` utility function removes specified keys from a Record Type Definition.\n\n```ts\nconst typeDefOne = Type.Record({\n  foo: Type.Number,\n  bar: Type.Number,\n  baz: Type.Number,\n  qux: Type.Number,\n});\n\nconst typeDefOmitted = Omit(typeDefOne, \"bar\", \"qux\");\n// typeDefOmitted = {\n//    foo: number;\n//    baz: number;\n// }\n```\n\n#### Pick()\n\n`Pick()` utility function removes all not specified keys from a Record Type\nDefinition.\n\n```ts\nconst typeDefOne = Type.Record({\n  foo: Type.Number,\n  bar: Type.Number,\n  baz: Type.Number,\n  qux: Type.Number,\n});\n\nconst typeDefPick = Pick(typeDefOne, \"bar\", \"qux\");\n// typeDefPick = {\n//    bar: number;\n//    qux: number;\n// }\n```\n\n#### Partial()\n\n`Partial()` utility type makes all the Record's Type Definition keys optional.\n\n```ts\nconst typeDefOne = Type.Record({\n  foo: Type.Number,\n  bar: Type.String,\n  baz: Type.Array(Type.Number),\n});\n\nconst typeDefPartial = Partial(typeDefOne);\n// typeDefPartial = {\n//    foo?: number | undefined;\n//    bar?: string | undefined;\n//    baz?: number[] | undefined;\n// }\n```\n\n#### Required()\n\n`Required()` utility type makes all the Record's Type Definition keys to be\nrequired (vs optional).\n\n```ts\nconst typeDefOne = Type.Record({\n  foo: { type: Type.Number, required: false },\n  bar: { type: Type.String, required: false },\n  baz: { type: Type.Array(Type.Number), required: false },\n});\n\nconst typeDefRequired = Required(typeDefOne);\n// typeDefRequired = {\n//    foo: number;\n//    bar: string;\n//    baz: number[];\n// }\n```\n\n#### Exclude()\n\n`Exclude()` utility function removes Type Definitions from an Type Def union.\n\n```ts\nconst typeDefOne = Type.OneOf(\n  Type.String,\n  Type.Number,\n  Type.Boolean,\n);\n\nconst typeDefExcluded = Exclude(typeDefOne, DataType.Number);\n// typeDefExcluded = string | boolean;\n```\n\n## Metadata\n\nEach Type can have metadata attached to it, this metadata can be used to\nprovide additional information about the data type, for example, you can attach\na description to a Type, or a title, or format.\n\n**Metadata is completely ignored by the validation process**\n\n### Assign Metadata\n\n```ts\nimport { Type } from \"dilswer\";\n\nconst UserNameDT = Type.String.setTitle(\"User Name\").setDescription(\n  \"The user's name.\",\n);\n\nconst User = Type.Record({\n  name: UserNameDT,\n  id: Type.String.setTitle(\"User ID\").setFormat(\"uuid\"),\n  friends: Type.Array(Type.String).setDescription(\n    \"A list of the user's friends names.\",\n  ),\n})\n  .setTitle(\"User\")\n  .setDescription(\n    \"A user object. Contains the user's name, id and friends list.\",\n  );\n```\n\n### Read Metadata\n\n```ts\nimport { Type, getMetadata } from \"dilswer\";\n\nconst userNameMetadata = getMetadata(UserNameDT);\n\n// userNameMetadata = {\n//   title: \"User Name\",\n//   description: \"The user's name.\",\n// }\n\nconst userMetadata = getMetadata(User);\n\n// userMetadata = {\n//  title: \"User\",\n//  description: \"A user object. Contains the user's name, id and friends list.\",\n// }\n```\n\n### Metadata and JSON Schema's\n\nMetadata is also used when generating JSON Schema, if a DataType has a title,\ndescription or format, it will be included in the generated JSON Schema.\n\n```ts\nimport { Type, toJsonSchema } from \"dilswer\";\n\nconst UserDT = Type.Record({\n  name: Type.String.setTitle(\"User Name\").setDescription(\n    \"The user's name.\",\n  ),\n  id: Type.String.setTitle(\"User ID\").setFormat(\"uuid\"),\n  friends: Type.Array(Type.String).setDescription(\n    \"A list of the user's friends names.\",\n  ),\n})\n  .setTitle(\"User\")\n  .setDescription(\n    \"A user object. Contains the user's name, id and friends list.\",\n  );\n\nconst jsonSchema = toJsonSchema(UserDT);\n\n//  jsonSchema = {\n//    title: \"User\",\n//    description: \"A user object. Contains the user's name, id and friends list.\",\n//    properties: {\n//      name: {\n//        type: \"string\",\n//        title: \"User Name\",\n//        description: \"The user's name.\",\n//      },\n//      id: {\n//        type: \"string\",\n//        title: \"User ID\",\n//        format: \"uuid\",\n//      },\n//      friends: {\n//        type: \"array\",\n//        items: {\n//          type: \"string\",\n//        },\n//      },\n//    },\n//    required: [\"name\", \"id\", \"friends\"],\n// }\n```\n\n### Parsing\n\nDilswer data types can be easily parsed into any arbitrary data structure via\n`parseWith` function.\n\nThis function takes a `visitor` object, which should contain a `visit` method,\nthis method should generate a node of the new, desired data structure.\n\nThis method is also used internally by `toJsonSchema` and `toTsType` functions.\nYou can see the implementation of these functions in the source code\n[here](./src/json-schema-parser/to-json-schema.ts) and\n[here](./src/ts-type-generator/to-ts-type.ts).\n\n#### Example\n\n```ts\nimport { AnyType, Type, parseWith } from \"dilswer\";\n\n// Define how the new structure should look like\ntype TypeNode = {\n  typeName: string;\n  children?: TypeNode[] | Record\u003cstring, TypeNode\u003e;\n};\n\n// Create a visitor which will be used to translate Dilswer's data types into `Node`s\nconst visitor = {\n  visit(\n    type: AnyType,\n    children?: TypeNode[] | RecordOfVisitChild\u003cTypeNode\u003e[],\n  ): TypeNode {\n    switch (type.kind) {\n      case \"simple\":\n        return { typeName: type.simpleType };\n      case \"record\":\n        return {\n          typeName: \"record\",\n          children: children\n            ? Object.fromEntries(\n              (children as RecordOfVisitChild\u003cNode\u003e[]).map(\n                ({ propertyName, child }) =\u003e [propertyName, child],\n              ),\n            )\n            : undefined,\n        };\n      default:\n        return { typeName: type.kind, children: children as Node[] };\n    }\n  },\n};\n\n// use the visitor on a Dilser data type\n\nconst type = Type.Record({\n  foo: Type.String,\n  bar: Type.Array(Type.Number),\n  baz: Type.OneOf(Type.String, Type.Number),\n});\n\nconst nodeTree = parseWith(visitor, type);\n```\n\n##### Example output\n\n```json\n{\n  \"typeName\": \"record\",\n  \"children\": {\n    \"foo\": {\n      \"typeName\": \"string\"\n    },\n    \"bar\": {\n      \"typeName\": \"array\",\n      \"children\": [\n        {\n          \"typeName\": \"number\"\n        }\n      ]\n    },\n    \"baz\": {\n      \"typeName\": \"union\",\n      \"children\": [\n        {\n          \"typeName\": \"string\"\n        },\n        {\n          \"typeName\": \"number\"\n        }\n      ]\n    }\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncpa0%2Fdilswer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fncpa0%2Fdilswer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncpa0%2Fdilswer/lists"}