{"id":18892335,"url":"https://github.com/hf/toi","last_synced_at":"2025-04-14T23:31:31.090Z","repository":{"id":48295538,"uuid":"112161245","full_name":"hf/toi","owner":"hf","description":"A TypeScript validation library capable of inferring types","archived":false,"fork":false,"pushed_at":"2021-08-02T20:50:06.000Z","size":411,"stargazers_count":28,"open_issues_count":22,"forks_count":8,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-12T09:42:27.036Z","etag":null,"topics":["dynamodb","joi","joi-validation","typescript","validation","validation-schema","validator"],"latest_commit_sha":null,"homepage":null,"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/hf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-27T07:13:18.000Z","updated_at":"2025-04-04T22:23:48.000Z","dependencies_parsed_at":"2022-08-30T15:21:48.528Z","dependency_job_id":null,"html_url":"https://github.com/hf/toi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Ftoi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Ftoi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Ftoi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hf%2Ftoi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hf","download_url":"https://codeload.github.com/hf/toi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248978727,"owners_count":21192834,"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","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":["dynamodb","joi","joi-validation","typescript","validation","validation-schema","validator"],"created_at":"2024-11-08T08:01:26.781Z","updated_at":"2025-04-14T23:31:30.853Z","avatar_url":"https://github.com/hf.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Toi\n\n[![Build Status](https://travis-ci.org/hf/toi.svg?branch=master)](https://travis-ci.org/hf/toi) [![codecov](https://codecov.io/gh/hf/toi/branch/master/graph/badge.svg)](https://codecov.io/gh/hf/toi)\n\nToi is a validator for JavaScript values written in TypeScript.\n\nIt's heavily inspired by [Joi](https://github.com/hapijs/joi), but actually\nuses different features from TypeScript's type system to infer the output type\nof a validation schema.\n\n## How to use?\n\nIt comes in two related packages:\n\n- `@toi/toi` which contains the most basic validators. You can see the source in\n  `packages/toi`.\n- `@toi/toix` which contains extra and commonly used validators. You can see the\n  source in `packages/toix`.\n\nUnlike Joi, it takes a more flexible and monadic approach to building\nvalidation schemas.\n\n### Install\n\nIt's packaged under the organization scope `@toi`. Just do:\n\n```\n# for toi\nyarn add @toi/toi\nnpm i --save @toi/toi\n\n# for toix\nyarn add @toi/toix\nnpm i --save @toi/toix\n```\n\nThe major versions of these two packages will always be in sync. It's\nrecommended you use the caret semver. Currently that is: `@^1.0.0`.\n\n### What's a validation schema?\n\nA validation schema is just a function that has type information about what\nit's inputs must be and what the output must be. You invoke this function over\nthe defined input, and you'll be sure to receive the defined output. Toi makes\nit easy to combine validation schemas to build rich output types.\n\nA validator, i.e. a validation schema, has the type `toi.Validator\u003cInput, Output\u003e`. You can make your own validators easily by using the heper function\n`toi.wrap`.\n\nValidators can be combined with the `and` function. In full honesty, it acts\nlike the logical conjucation operator, but it's really more of a `bind` or\n`map` operator seen in monads. Effecitvely, it composes the validator function\non which it's called and the provided validation function.\n\nEach validator must obey these rules:\n\n- Must always accept `null` and `undefined` as values, unless really special.\n- Must always throw a `ValidationError` if the value is not expected.\n- Must throw any non-validation errors as early as possible.\n- Must return the correct value passed to them. This value may be transformed.\n\n### How it works?\n\nLet's take a look at some common patterns and how they work with Toi.\n\nHere's a validation schema for all objects of the form `{ num: number; str: string }`.\n\n```typescript\nimport * as toi from \"@toi/toi\";\n\nconst isObject = toi\n  .required() // make toi reject null or undefined\n  .and(toi.obj.isplain()) // forces that the value is a plain JS object\n  .and(\n    toi.obj.keys({\n      num: toi.required().and(toi.num.is()),\n      str: toi.required().and(toi.str.is())\n    })\n  ); // makes sure that the object has props num, str that are never null\n\nisObject({ num: 1, str: \"1\" }); // will pass\nisObject(null); // will throw toi.ValidationError\n```\n\nYou can use `toi.required()` or `toi.optional()` to enforce strict non-null\nrules. In TypeScript 2.8 there are conditional types, and these methods use\nthem to infer whether the starting value is nullable, therefore propagate that\ntype information down the chain.\n\nIt is sometimes possible to skip using these, if you already know what type\nyou'll be validating. It's also possible to just not use them at all, in which\ncase nullable type information will not be propagated down the chain. It\ndoesn't mean tho, that the value is non-null!\n\n### All the validators!\n\nToi and ToiX are laid out in a specific way, to help you identify validators\neasily:\n\n`toi` is the toplevel module. It contains the following submodules:\n\n- `num` includes validators that work with numbers\n- `str` includes validators that work with strings\n- `bool` includes validators that work with booleans\n- `obj` includes validators that work with objects\n- `array` includes validators that work with arrays\n- `date` includes validators that work with dates\n- `any` includes validators for any value\n- `optional` special validator for starting a nullable chain\n- `required` special validator for starting a non-nullable chain\n\nEach submodule contains a method named `is` that does the most basic type\ncheck. For example: `toi.num.is()` validates that the value provided is a\nnumber, `toi.str.is()` validates that the value provided is a string, etc.\n\nInside each submodule you'll find different validators for different types of\nvalidations.\n\nOne of the goals for Toi is to have really readable code, and you should really\ntake a look at it in order to find the validators you want. In fact, the\nwebsite is just Toi!\n\n### Validation Errors\n\nYou can inspect each `toi.ValidationError` via the `reasons` property. If set,\nit will mimic the shape of the value that failed validation. So, if an object\nfails validation due to some of its properties failing validation, the\n`reasons` property will be an object with properties that map to other\n`toi.ValidationError`s which caused the validation failure. Similarly it works\nfor arrays.\n\n### Writing your own validators?\n\nIt's real easy. First, make sure you obey the rules for each validator.\nOtherwise, there are three methods that will make your life easier:\n\n1.  `toi.wrap(\"name-in-stack-trace\", value =\u003e value)` to convert a simple\n    validation function into a full-blown `toi.Validator`.\n2.  `toi.allow(value =\u003e !value, \"value is truthy\")` to create a simple\n    validation function that obeys the rules, from a function that returns\n    `true` if the validation passes, or `false` if it does not. You still have\n    to use `toi.wrap` on top of this.\n3.  `toi.transform(value =\u003e value + 1)` to create a simple validation function\n    that transforms a value into a different value, and obeys the rules. You\n    still have to use `toi.wrap` on top of this.\n\n## Contributing\n\nOnly the basic validators out of which you can build more complex validators\nshould be placed in the `toi` package. Everything else should go into `toix`.\n\nTest coverage must be 100% for both packages. If you don't like it, please make\nyour own library. Toi was designed to be easy to interoperate with custom\nvalidators (unlike Joi).\n\nTests must test what the documentation says. Don't test JavaScript runtime\nmethods, but do explicitly say that they're used.\n\n## License\n\nCopyright \u0026copy; 2018 Stojan Dimitrovski, some rights reserved.\n\nLicensed under the MIT license. You can get a copy of it in `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhf%2Ftoi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhf%2Ftoi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhf%2Ftoi/lists"}