{"id":25356473,"url":"https://github.com/jacob-alford/schemata-ts","last_synced_at":"2025-07-18T11:38:22.215Z","repository":{"id":59353897,"uuid":"534427566","full_name":"jacob-alford/schemata-ts","owner":"jacob-alford","description":"An all-inclusive schema engine featuring schemata inspired by io-ts and validators.js.  Written for TypeScript with fp-ts","archived":false,"fork":false,"pushed_at":"2025-04-24T22:19:54.000Z","size":3560,"stargazers_count":34,"open_issues_count":3,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-06-29T10:04:11.046Z","etag":null,"topics":["camelcase-keys","deserialization","json-schema","parser","serialization","validator"],"latest_commit_sha":null,"homepage":"https://schemata.jacob-alford.dev/","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/jacob-alford.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":"2022-09-08T23:25:02.000Z","updated_at":"2025-04-24T22:13:59.000Z","dependencies_parsed_at":"2023-11-29T19:30:13.065Z","dependency_job_id":"d90221e8-15d6-4f58-9319-e9952654ceca","html_url":"https://github.com/jacob-alford/schemata-ts","commit_stats":{"total_commits":446,"total_committers":9,"mean_commits":49.55555555555556,"dds":0.1659192825112108,"last_synced_commit":"5527d88faf0016cc529f4be08773d923d4dd1362"},"previous_names":["jacob-alford/schemable-ts-types"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/jacob-alford/schemata-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-alford%2Fschemata-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-alford%2Fschemata-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-alford%2Fschemata-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-alford%2Fschemata-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jacob-alford","download_url":"https://codeload.github.com/jacob-alford/schemata-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacob-alford%2Fschemata-ts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265753028,"owners_count":23823073,"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":["camelcase-keys","deserialization","json-schema","parser","serialization","validator"],"created_at":"2025-02-14T20:47:30.869Z","updated_at":"2025-07-18T11:38:22.192Z","avatar_url":"https://github.com/jacob-alford.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/jacob-alford/schemata-ts/main/assets/schemata-purple.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/jacob-alford/schemata-ts/main/assets/schemata-white.png\"\u003e\n    \u003cimg alt=\"schemata-ts\" src=\"https://raw.githubusercontent.com/jacob-alford/schemata-ts/main/assets/schemata-blue.png\"\u003e\n  \u003c/picture\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\u003ch1 align=\"center\"\u003e\n🔭\u0026nbsp;\u0026nbsp;\u0026nbsp;schemata-ts\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\nAn all-inclusive schema engine featuring schemata inspired by io-ts and validators.js.  Written for TypeScript with fp-ts\n\u003c/p\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n\u003cimg alt=\"npm\" src=\"https://img.shields.io/npm/v/schemata-ts?style=for-the-badge\u0026logo=npm\"\u003e\n\u0026nbsp;\n\u003cimg alt=\"TypeScript\" src=\"https://img.shields.io/badge/TypeScript-4.5%2B-blue?style=for-the-badge\u0026logo=TypeScript\"\u003e\n\u0026nbsp;\n\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\n\u003cimg alt=\"npm\" src=\"https://img.shields.io/npm/dt/schemata-ts?style=for-the-badge\"\u003e\n\u0026nbsp;\n\u003cimg alt=\"Coveralls branch\" src=\"https://img.shields.io/coverallsCoverage/github/jacob-alford/schemata-ts?style=for-the-badge\"\u003e\n\u0026nbsp;\n\u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/jacob-alford/schemata-ts?style=for-the-badge\"\u003e\n\u0026nbsp;\n\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\n\u003cimg alt=\"Static Badge\" src=\"https://img.shields.io/badge/ESM-Supported-success?style=for-the-badge\u0026logo=JavaScript\"\u003e\n\u0026nbsp;\n\u003cimg alt=\"Static Badge\" src=\"https://img.shields.io/badge/CJS-supported-success?style=for-the-badge\u0026logo=Node.JS\"\u003e\n\u0026nbsp;\n\n\u003c/div\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://jacob-alford.github.io/schemata-ts/\"\u003eDocumentation\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;•\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://www.npmjs.com/package/schemata-ts\"\u003enpm\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;•\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/jacob-alford/schemata-ts/issues/new\"\u003eIssues\u003c/a\u003e\n  \u003cbr /\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\u003cbr\u003e\n\n# Welcome\n\n`Schemata-ts` is an unofficial continuation of `io-ts` v2 built from the ground up using the highly extensible `Schemable`/`Schema` API. Schemata also comes with a suite of string validation schemas and branded types — powered by [Kuvio](https://github.com/skeate/kuvio) — all inspired by io-ts-types and validators.js.\n\n|     | Features                                                                               |\n| --- | -------------------------------------------------------------------------------------- |\n| ✅  | [Validation, Parsing, and Serialization](#validation-parsing-and-serialization)        |\n| ✅  | [Type Guards](#type-guards)                                                            |\n| ✅  | [Json-Schema Draft 07, 2019-09, and 2020-12](#json-schema-draft-7-2019-09-and-2020-12) |\n| ✅  | [Fast-Check Arbitraries](#fast-check-arbitraries)                                      |\n| ✅  | [and more](#and-more)                                                                  |\n\n## Installation\n\n### Yarn\n\n```console\nyarn add schemata-ts\n```\n\n### NPM\n\n```console\nnpm install schemata-ts\n```\n\n### PNPM\n\n```console\npnpm add schemata-ts\n```\n\n**A note on fast-check:** Schemata lists `fast-check` as a peer dependency. As a result, it doesn't need to be installed for schemata to work. It is recommended to install `fast-check` as a dev dependency which will satisfy the peer dependency requirement. To avoid fast-check being bundled in a front-end application, only import from the `Arbitrary` module in test files.\n\n## Schema\n\nA `Schema` is a simple function that's architected using service-oriented principles. It's a function that takes a `Schemable` which is an interface of capabilities that produce a particular data-type. Schemas aren't intended to be constructed by users of the library but instead are pre-constructed and exported from the root directory.\n\nThe following import will give you access to all of the pre-constructed schemas.\n\n```ts\nimport * as S from 'schemata-ts'\n```\n\nIn addition to \"primitive\" schemas like `S.String(params?)`, `S.Int(params?)`, `S.Boolean`, schemata-ts also exports schema _combinators_ from the root directory. 'Combinator' is a fancy word for a function that takes one or more schemas and returns a new schema. For example, `S.Array(S.String())` is a schema over an array of strings, and `S.Struct({ foo: S.String() })` is a schema over an object with a single property `foo` which is a string.\n\n- [Docs](https://jacob-alford.github.io/schemata-ts/schema)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/Schema.ts)\n- [View All Schemata](https://jacob-alford.github.io/schemata-ts/schemata)\n- [All Schemata Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata)\n\n### Schema Example\n\n```ts\nimport * as S from 'schemata-ts'\n\nexport const PersonSchema = S.Struct({\n  name: S.String(),\n  age: S.Int({ min: 0, max: 120 }),\n  isCool: S.Boolean,\n  favoriteColors: S.Array(S.String()),\n})\n```\n\n## Schema Transformations\n\nThere are three ways to transform a schema in `schemata-ts`: ['combinators'](#schema) which are functions that take schemas as parameters and return new schemas, 'transformers' which are specific to particular schemata, and `Imap` which applies an invariant transformation to the underlying data-type.\n\n### Invariant Transformations\n\nAside from `Guard`, all data-types derivable from schemas are invariant functors. This means that supplying mapping functions `to` and `from` to `Imap` adjusts the `Output` of that particular data type. Because `Guard` is not invariant, you must supply the resulting `Guard` to the invariant map. The combinator version of this is `Imap`. In version `3.0` (coming late 2023/early 2024) it will be possible to `.imap()` any schema.\n\n### Schema Transformers\n\nSchema transformers are classes which extend `SchemaImplementation`, and allow adjustment to the underlying schema parameters after it has been declared in an immutable fashion. This is useful for type-specific methods like `pick` or `omit` for `Struct`.\n\nHere are the current transformers and available methods,\n\n- Struct: `pick`, `omit`, `partial`, `partialOption`, `readonly`, `strict`, `addIndexSignature`, `extend`, `intersect`\n- Array: `minLength`, `maxLength`, `nonEmpty`\n- String: `brand`, `minLength`, `maxLength`, `errorName`\n- Int: `brand`, `min`, `max`, `errorName`\n- Float: `brand`, `min`, `max`, `errorName`\n- Tuple: `append`, `prepend`\n\n... with more to come!\n\n### Transformation Example\n\n```typescript\nconst SoftwareDeveloperSchema = PersonSchema.omit('isCool')\n  .extend({\n    favoriteLanguages: S.Array(S.String()),\n    favoriteFrameworks: S.Array(S.String()),\n  })\n  .strict()\n```\n\n## TypeScript Types\n\nSchemas can be used to extract the underlying TypeScript type to avoid writing the same definition twice and different parts of code getting out of sync.\n\nSchemas have reference to both the input and output type. The input type is more often for usage outside of JavaScript land (such as over the wire in an API request), and the output type is more often for usage within JavaScript land.\n\n```ts\nexport type Person = S.OutputOf\u003ctypeof PersonSchema\u003e\n\nexport type PersonInput = S.InputOf\u003ctypeof PersonSchema\u003e\n```\n\n## Validation, Parsing, and Serialization\n\n`Schemata-ts`'s type-class for validation and parsing is called \"Transcoder.\" Transcoders can be derived from schemas using `deriveTranscoder`:\n\n```ts\nimport { deriveTranscoder, type Transcoder } from 'schemata-ts/Transcoder'\n\nconst personTranscoder: Transcoder\u003cPersonInput, Person\u003e = deriveTranscoder(PersonSchema)\n```\n\nTranscoders are intended to succeed `Decoder`, `Encoder`, and `Codec` from `io-ts` v2. They contain two methods: `decode` and `encode`. The `decode` method takes an unknown value to an fp-ts `Either` type where the failure type is a `schemata-ts` error tree called `TranscodeError`, and the success type is the output type of the schema.\n\n- [Documentation](https://jacob-alford.github.io/schemata-ts/transcoder)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/Transcoder.ts)\n\n### Transcoder Transformations (_Advanced_)\n\nIn addition to parsing an unknown value, Transcoder can _transform_ input types. One example is `MapFromEntries` which takes an array of key-value pairs and transforms it into a JavaScript `Map` type.\n\n```ts\nimport * as Str from 'fp-ts/string'\n\nconst PeopleSchema = S.MapFromEntries(Str.Ord, S.String(), PersonSchema)\n\nconst peopleTranscoder: Transcoder\u003c\n  ReadonlyArray\u003creadonly [string, PersonInput]\u003e,\n  ReadonlyMap\u003cstring, Person\u003e\n\u003e = deriveTranscoder(PeopleSchema)\n```\n\n### Transcoder Serialization (_Advanced_)\n\nSchemas can be turned into printer-parsers using various `Parser` schemas, such as:\n\n(De)Serialization from Json String:\n\n```ts\nconst parsePersonTranscoder: Transcoder\u003cS.JsonString, Person\u003e = deriveTranscoder(\n  S.ParseJsonString(PersonSchema),\n)\n```\n\nor, (De)Serialization from a Base-64 encoded Json String:\n\n```ts\nconst parsePersonTranscoder: Transcoder\u003cS.Base64, Person\u003e = deriveTranscoder(\n  S.ParseBase64Json(PersonSchema),\n)\n```\n\n### Transcoder Parallelized Validation (_Advanced_)\n\nTranscoders can be parallelized using `TranscoderPar` which is a typeclass similar to Transcoder but returns `TaskEither`s instead of `Either`s. This allows for parallelized validation for schemas of multiple values like structs and arrays.\n\n```ts\nimport { deriveTranscoderPar, type TranscoderPar } from 'schemata-ts/TranscoderPar'\n\nconst personTranscoderPar: TranscoderPar\u003cPersonInput, Person\u003e =\n  deriveTranscoderPar(PersonSchema)\n```\n\n### Transcoder Documentation\n\n- [Documentation](https://jacob-alford.github.io/schemata-ts/transcoder-par)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/TranscoderPar.ts)\n\n## Type Guards\n\nType guards are used by TypeScript to narrow the type of a value to something concrete. Guards can be derived from schemas using `deriveGuard`:\n\n```ts\nimport { deriveGuard, type Guard } from 'schemata-ts/Guard'\n\nconst guardPerson: Guard\u003cPerson\u003e = deriveGuard(PersonSchema)\n```\n\n### Type Guard Documentation\n\n- [Documentation](https://jacob-alford.github.io/schemata-ts/guard)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/Guard.ts)\n\n## JSON Schema (Draft 7, 2019-09, and 2020-12)\n\nJson-Schema is a standard for describing JSON data. Schemata-ts can derive Json-Schema from schemas using `deriveJsonSchema` for versions Draft-07, 2019-09, and 2020-12.\n\n```ts\nimport { deriveJsonSchema } from 'schemata-ts/JsonSchema'\n\nconst personJsonSchemaDraft07 = deriveJsonSchema(PersonSchema, 'Draft-07')\nconst personJsonSchema2019 = deriveJsonSchema(PersonSchema)\nconst personJsonSchema2020 = deriveJsonSchema(PersonSchema, '2020-12')\n```\n\n### JSON Schema Documentation\n\n- [Documentation](https://jacob-alford.github.io/schemata-ts/json-schema)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/JsonSchema.ts)\n- [Specification](https://json-schema.org/specification)\n\n## Fast-Check Arbitraries\n\nFast-Check is a property-based testing library for JavaScript. Schemata-ts can derive fast-check arbitraries from schemas using `deriveArbitrary`:\n\n```ts\nimport * as fc from 'fast-check'\nimport { deriveArbitrary } from 'schemata-ts/Arbitrary'\n\nconst personArbitrary = deriveArbitrary(PersonSchema).arbitrary(fc)\n```\n\n### Arbitrary Documentation\n\n- [Documentation](https://jacob-alford.github.io/schemata-ts/arbitrary)\n- [Source](https://github.com/jacob-alford/schemata-ts/tree/main/src/Arbitrary.ts)\n- [Fast-Check](https://github.com/dubzzz/fast-check)\n\n## And more\n\nSchemata has other derivations besides the ones above, below are links to those places in the documentation.\n\n- [MergeSemigroup](https://jacob-alford.github.io/schemata-ts/merge-semigroup): A customizable schema specific deep-merge ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/MergeSemigroup.ts))\n- [Eq](https://jacob-alford.github.io/schemata-ts/eq): A schema-specific equality check ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/Eq.ts))\n- [TypeString](https://jacob-alford.github.io/schemata-ts/type-string): Input / Output type strings ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/TypeString.ts))\n\n# Contributors ✨\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n\n[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-)\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/jacob-alford\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7153123?v=4?s=100\" width=\"100px;\" alt=\"Jacob Alford\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJacob Alford\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/jacob-alford/schemata-ts/commits?author=jacob-alford\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/newswim\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6667096?v=4?s=100\" width=\"100px;\" alt=\"Dan Minshew\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDan Minshew\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/jacob-alford/schemata-ts/commits?author=newswim\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://skeate.dev\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/387382?v=4?s=100\" width=\"100px;\" alt=\"Jonathan Skeate\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJonathan Skeate\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/jacob-alford/schemata-ts/commits?author=skeate\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/0x706b\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/20319430?v=4?s=100\" width=\"100px;\" alt=\"Peter Krol\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePeter Krol\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/jacob-alford/schemata-ts/commits?author=0x706b\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/golergka\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/929735?v=4?s=100\" width=\"100px;\" alt=\"golergka\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003egolergka\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/jacob-alford/schemata-ts/commits?author=golergka\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacob-alford%2Fschemata-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacob-alford%2Fschemata-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacob-alford%2Fschemata-ts/lists"}