{"_id":"@sroussey/json-schema-to-ts","_rev":"2-a129f0eacd4dffa59c15abe7e17f0f74","name":"@sroussey/json-schema-to-ts","dist-tags":{"latest":"3.1.4"},"versions":{"3.1.3":{"name":"@sroussey/json-schema-to-ts","version":"3.1.3","keywords":["json","schema","typescript","type","ts"],"author":{"name":"Thomas Aribart"},"license":"MIT","_id":"@sroussey/json-schema-to-ts@3.1.3","maintainers":[{"name":"sroussey","email":"sroussey@gmail.com"}],"contributors":[{"url":"https://github.com/sroussey","name":"sroussey"}],"homepage":"https://github.com/ThomasAribart/json-schema-to-ts#readme","bugs":{"url":"https://github.com/ThomasAribart/json-schema-to-ts/issues"},"dist":{"shasum":"6fc6a8306cf6816038c30908ad123b72f94fd199","tarball":"https://registry.npmjs.org/@sroussey/json-schema-to-ts/-/json-schema-to-ts-3.1.3.tgz","fileCount":267,"integrity":"sha512-N4j/Mz1YkZHvQfStIvtS4DiQLltzzU84jFt6qoo0DsUHV+n3UDfduWlYQSwov8gS9iJliIJ4L4Vb15k5HVdLwg==","signatures":[{"sig":"MEYCIQDDdjRBXh/WRPebgaxUd5/GowfGV4KY3jQE7En6ZX3Z8AIhAOny3xBadPpgURdJsFKxDFdDCXaWo+VKvb3wJ+M36DLu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":258280},"main":"lib/cjs/index.js","types":"lib/types/index.d.ts","module":"lib/esm/index.js","engines":{"node":">=16"},"gitHead":"5a7fcd43cf26ab25bd9bb0fb4084327c31a41c90","scripts":{"test":"yarn test-type && yarn test-format && yarn test-unit && yarn test-unused-exports && yarn test-lint","build":"rm -rf lib && yarn build-cjs && yarn build-esm && yarn build-types","format":"yarn prettier . --write","build-cjs":"NODE_ENV=cjs yarn transpile --out-dir lib/cjs --source-maps","build-esm":"NODE_ENV=esm yarn transpile --out-dir lib/esm --source-maps","test-lint":"yarn eslint --ext=js,ts .","test-type":"tsc --noEmit","test-unit":"jest --verbose --runInBand --collectCoverage --logHeapUsage --passWithNoTests","transpile":"babel src --extensions .ts --quiet","build-types":"tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json","test-format":"yarn prettier src --check","test-circular":"yarn depcruise --validate .dependency-cruiser.js ./src","set-package-version":"ts-node scripts/setPackageVersion","test-unused-exports":"yarn ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/index.ts;'"},"_npmUser":{"name":"sroussey","email":"sroussey@gmail.com"},"repository":{"url":"git+https://github.com/sroussey/json-schema-to-ts.git","type":"git"},"_npmVersion":"11.6.4","description":"Infer typescript types from your JSON schemas!","directories":{},"_nodeVersion":"24.10.0","dependencies":{"ts-algebra":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.17.1","jest":"^30.2.0","eslint":"^8.57.1","rollup":"^2.79.2","ts-jest":"^29.4.6","ts-node":"^10.9.2","prettier":"^3.7.4","tsc-alias":"^1.8.16","@babel/cli":"^7.28.0","typescript":"^5.9.3","@babel/core":"^7.28.0","@types/jest":"^27.5.2","@types/node":"^20.19.26","ts-toolbelt":"^9.6.0","@babel/runtime":"^7.28.0","@babel/preset-env":"^7.28.0","rollup-plugin-dts":"6.3.0","ts-unused-exports":"^8.0.5","dependency-cruiser":"^17.3.2","eslint-plugin-jest":"^27.9.0","eslint-plugin-jsdoc":"^46.10.1","eslint-plugin-import":"^2.32.0","eslint-config-prettier":"^8.10.2","eslint-plugin-prettier":"^5.5.4","@babel/preset-typescript":"^7.28.0","rollup-plugin-import-map":"^3.0.0","@rollup/plugin-typescript":"^8.5.0","@typescript-eslint/parser":"^6.21.0","eslint-plugin-prefer-arrow":"^1.2.3","@zerollup/ts-transform-paths":"^1.7.18","babel-plugin-module-resolver":"^5.0.2","eslint-plugin-unused-imports":"^4.3.0","rollup-plugin-typescript-paths":"^1.5.0","@babel/plugin-transform-runtime":"^7.28.0","@typescript-eslint/eslint-plugin":"^6.21.0","eslint-import-resolver-typescript":"^3.10.1","@trivago/prettier-plugin-sort-imports":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/json-schema-to-ts_3.1.3_1765245004456_0.25797706329090775","host":"s3://npm-registry-packages-npm-production"}},"3.1.4":{"name":"@sroussey/json-schema-to-ts","version":"3.1.4","description":"Infer typescript types from your JSON schemas!","main":"lib/cjs/index.js","module":"lib/esm/index.js","types":"lib/types/index.d.ts","scripts":{"test":"yarn test-type && yarn test-format && yarn test-unit && yarn test-unused-exports && yarn test-lint","test-type":"tsc --noEmit","test-format":"yarn prettier src --check","test-unit":"jest --verbose --runInBand --collectCoverage --logHeapUsage --passWithNoTests","test-unused-exports":"yarn ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/index.ts;'","test-lint":"yarn eslint --ext=js,ts .","format":"yarn prettier . --write","test-circular":"yarn depcruise --validate .dependency-cruiser.js ./src","transpile":"babel src --extensions .ts --quiet","build":"rm -rf lib && yarn build-cjs && yarn build-esm && yarn build-types","build-cjs":"NODE_ENV=cjs yarn transpile --out-dir lib/cjs --source-maps","build-esm":"NODE_ENV=esm yarn transpile --out-dir lib/esm --source-maps","build-types":"tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json","set-package-version":"ts-node scripts/setPackageVersion","benchmark-types":"ts-node scripts/benchmark-types.ts","benchmark-types:baseline":"ts-node scripts/benchmark-types.ts --iterations 10 --format markdown","benchmark-types:diagnostics":"ts-node scripts/benchmark-types.ts --config tsconfig.benchmark.json --iterations 3","measure-instantiation":"ts-node scripts/measure-instantiation.ts"},"dependencies":{"@sroussey/ts-algebra":"^2.0.0"},"devDependencies":{"@babel/cli":"^7.28.0","@babel/core":"^7.28.0","@babel/plugin-transform-runtime":"^7.28.0","@babel/preset-env":"^7.28.0","@babel/preset-typescript":"^7.28.0","@babel/runtime":"^7.28.0","@rollup/plugin-typescript":"^8.5.0","@trivago/prettier-plugin-sort-imports":"^6.0.0","@types/jest":"^27.5.2","@types/node":"^20.19.26","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","@zerollup/ts-transform-paths":"^1.7.18","ajv":"^8.17.1","babel-plugin-module-resolver":"^5.0.2","dependency-cruiser":"^17.3.2","eslint":"^8.57.1","eslint-config-prettier":"^8.10.2","eslint-import-resolver-typescript":"^3.10.1","eslint-plugin-import":"^2.32.0","eslint-plugin-jest":"^27.9.0","eslint-plugin-jsdoc":"^46.10.1","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-prettier":"^5.5.4","eslint-plugin-unused-imports":"^4.3.0","jest":"^30.2.0","prettier":"^3.7.4","rollup":"^2.79.2","rollup-plugin-dts":"6.3.0","rollup-plugin-import-map":"^3.0.0","rollup-plugin-typescript-paths":"^1.5.0","ts-jest":"^29.4.6","ts-node":"^10.9.2","ts-toolbelt":"^9.6.0","ts-unused-exports":"^8.0.5","tsc-alias":"^1.8.16","typescript":"^5.9.3"},"engines":{"node":">=16"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/sroussey/json-schema-to-ts.git"},"keywords":["json","schema","typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/json-schema-to-ts/issues"},"homepage":"https://github.com/ThomasAribart/json-schema-to-ts#readme","contributors":[{"name":"sroussey","url":"https://github.com/sroussey"}],"gitHead":"0afcfc6fd91c7a301b4b3d467fe629ae7f271fd3","_id":"@sroussey/json-schema-to-ts@3.1.4","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-wGYvgjUI0MoFTICZSoqJEB16bvXJ8lViVHrl3GNNRH871fuk3L6QlsmhWgAr/J0UKHyL1Swz6FVo5ABJTifbKg==","shasum":"43f49559a9dbbbf3983971d625096779d90c119b","tarball":"https://registry.npmjs.org/@sroussey/json-schema-to-ts/-/json-schema-to-ts-3.1.4.tgz","fileCount":267,"unpackedSize":266095,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCctAC3h+GyDXCJq+w26hKEzHtzN605ReLyUzh7F+EOuAIgRw6O65ZuYnS3/54L4IYeDojjawH10TAJGgtcWlH7Vk8="}]},"_npmUser":{"name":"sroussey","email":"sroussey@gmail.com"},"directories":{},"maintainers":[{"name":"sroussey","email":"sroussey@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/json-schema-to-ts_3.1.4_1769192367794_0.8937798346257304"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-09T01:50:04.379Z","modified":"2026-01-23T18:19:28.048Z","3.1.3":"2025-12-09T01:50:04.632Z","3.1.4":"2026-01-23T18:19:27.944Z"},"bugs":{"url":"https://github.com/ThomasAribart/json-schema-to-ts/issues"},"author":{"name":"Thomas Aribart"},"license":"MIT","homepage":"https://github.com/ThomasAribart/json-schema-to-ts#readme","keywords":["json","schema","typescript","type","ts"],"repository":{"type":"git","url":"git+https://github.com/sroussey/json-schema-to-ts.git"},"description":"Infer typescript types from your JSON schemas!","contributors":[{"name":"sroussey","url":"https://github.com/sroussey"}],"maintainers":[{"name":"sroussey","email":"sroussey@gmail.com"}],"readme":"<img src=\"assets/header-round-medium.png\" width=\"100%\" align=\"center\" />\n\n💖 _Huge thanks to the [sponsors](https://github.com/sponsors/ThomasAribart) who help me maintain this repo:_\n\n<p align=\"center\">\n  <a href=\"https://www.theodo.fr/\"><img src=\"https://github.com/theodo.png\" width=\"50px\" alt=\"Theodo\" title=\"Theodo\"/></a></td>&nbsp;&nbsp;\n  <!-- sponsors --><a href=\"https://github.com/feathersdev\"><img src=\"https://github.com/feathersdev.png\" width=\"50px\" alt=\"feathers.dev\" title=\"feathers.dev\"/></a>&nbsp;&nbsp;<a href=\"https://github.com/li-jia-nan\"><img src=\"https://github.com/li-jia-nan.png\" width=\"50px\" alt=\"lijianan\" title=\"lijianan\"/></a>&nbsp;&nbsp;<a href=\"https://github.com/RaeesBhatti\"><img src=\"https://github.com/RaeesBhatti.png\" width=\"50px\" alt=\"Raees Iqbal\" title=\"Raees Iqbal\"/></a>&nbsp;&nbsp;<a href=\"https://github.com/lucas-subli\"><img src=\"https://github.com/lucas-subli.png\" width=\"50px\" alt=\"Lucas Saldanha Ferreira\" title=\"Lucas Saldanha Ferreira\"/></a>&nbsp;&nbsp;<a href=\"https://github.com/syntaxfm\"><img src=\"https://github.com/syntaxfm.png\" width=\"50px\" alt=\"Syntax\" title=\"Syntax\"/></a>&nbsp;&nbsp;<!-- sponsors -->\n  <a href=\"https://github.com/sponsors/ThomasAribart\"><img src=\"assets/plus-sign.png\" width=\"50px\" alt=\"Plus sign\" title=\"Your brand here!\"/></a>\n</p>\n\n# Stop typing twice 🙅‍♂️\n\nA lot of projects use JSON schemas for runtime data validation along with TypeScript for static type checking.\n\nTheir code may look like this:\n\n```typescript\nconst dogSchema = {\n  type: \"object\",\n  properties: {\n    name: { type: \"string\" },\n    age: { type: \"integer\" },\n    hobbies: { type: \"array\", items: { type: \"string\" } },\n    favoriteFood: { enum: [\"pizza\", \"taco\", \"fries\"] },\n  },\n  required: [\"name\", \"age\"],\n};\n\ntype Dog = {\n  name: string;\n  age: number;\n  hobbies?: string[];\n  favoriteFood?: \"pizza\" | \"taco\" | \"fries\";\n};\n```\n\nBoth objects carry similar if not exactly the same information. This is a code duplication that can annoy developers and introduce bugs if not properly maintained.\n\nThat's when `json-schema-to-ts` comes to the rescue 💪\n\n## FromSchema\n\nThe `FromSchema` method lets you infer TS types directly from JSON schemas:\n\n```typescript\nimport { FromSchema } from \"json-schema-to-ts\";\n\nconst dogSchema = {\n  type: \"object\",\n  properties: {\n    name: { type: \"string\" },\n    age: { type: \"integer\" },\n    hobbies: { type: \"array\", items: { type: \"string\" } },\n    favoriteFood: { enum: [\"pizza\", \"taco\", \"fries\"] },\n  },\n  required: [\"name\", \"age\"],\n} as const;\n\ntype Dog = FromSchema<typeof dogSchema>;\n// => Will infer the same type as above\n```\n\nSchemas can even be nested, as long as you don't forget the `as const` statement:\n\n```typescript\nconst catSchema = { ... } as const;\n\nconst petSchema = {\n  anyOf: [dogSchema, catSchema],\n} as const;\n\ntype Pet = FromSchema<typeof petSchema>;\n// => Will work 🙌\n```\n\nThe `as const` statement is used so that TypeScript takes the schema definition to the word (e.g. _true_ is interpreted as the _true_ constant and not widened as _boolean_). It is pure TypeScript and has zero impact on the compiled code.\n\nIf you don't mind impacting the compiled code, you can use the `asConst` util, which simply returns the schema while narrowing its inferred type.\n\n```typescript\nimport { asConst } from \"json-schema-to-ts\";\n\nconst dogSchema = asConst({\n  type: \"object\",\n  ...\n});\n\ntype Dog = FromSchema<typeof dogSchema>;\n// => Will work as well 🙌\n```\n\nSince TS 4.9, you can also use the `satisfies` operator to benefit from type-checking and autocompletion:\n\n```typescript\nimport type { JSONSchema } from \"json-schema-to-ts\";\n\nconst dogSchema = {\n  // Type-checked and autocompleted 🙌\n  type: \"object\"\n  ...\n} as const satisfies JSONSchema\n\ntype Dog = FromSchema<typeof dogSchema>\n// => Still work 🙌\n```\n\nYou can also use this with JSDocs by wrapping your schema in `/** @type {const} @satisfies {import('json-schema-to-ts').JSONSchema} */ (...)` like:\n\n```\nconst dogSchema = /** @type {const} @satisfies {import('json-schema-to-ts').JSONSchema} */ ({\n  // Type-checked and autocompleted 🙌\n  type: \"object\"\n  ...\n})\n\n/** @type {import('json-schema-to-ts').FromSchema<typeof dogSchema>} */\nconst dog = { ... }\n```\n\n## Why use `json-schema-to-ts`?\n\nIf you're looking for runtime validation with added types, libraries like [yup](https://github.com/jquense/yup), [zod](https://github.com/vriad/zod) or [runtypes](https://github.com/pelotom/runtypes) may suit your needs while being easier to use!\n\nOn the other hand, JSON schemas have the benefit of being widely used, more versatile and reusable (swaggers, APIaaS...).\n\nIf you prefer to stick to them and can define your schemas in TS instead of JSON (importing JSONs `as const` is not available yet), then `json-schema-to-ts` is made for you:\n\n- ✅ **Schema validation** `FromSchema` raises TS errors on invalid schemas, based on [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/json-schema)'s definitions\n- ✨ **No impact on compiled code**: `json-schema-to-ts` only operates in type space. And after all, what's lighter than a dev-dependency?\n- 🍸 **DRYness**: Less code means less embarrassing typos\n- 🤝 **Real-time consistency**: See that `string` that you used instead of an `enum`? Or this `additionalProperties` you confused with `additionalItems`? Or forgot entirely? Well, `json-schema-to-ts` does!\n- 🔧 **Reliability**: `FromSchema` is extensively tested against [AJV](https://github.com/ajv-validator/ajv), and covers all the use cases that can be handled by TS for now\\*\n- 🏋️‍♂️ **Help on complex schemas**: Get complex schemas right first time with instantaneous typing feedbacks! For instance, it's not obvious the following schema can never be validated:\n\n```typescript\nconst addressSchema = {\n  type: \"object\",\n  allOf: [\n    {\n      properties: {\n        street: { type: \"string\" },\n        city: { type: \"string\" },\n        state: { type: \"string\" },\n      },\n      required: [\"street\", \"city\", \"state\"],\n    },\n    {\n      properties: {\n        type: { enum: [\"residential\", \"business\"] },\n      },\n    },\n  ],\n  additionalProperties: false,\n} as const;\n```\n\nBut it is with `FromSchema`!\n\n```typescript\ntype Address = FromSchema<typeof addressSchema>;\n// => never 🙌\n```\n\n> \\*If `json-schema-to-ts` misses one of your use case, feel free to [open an issue](https://github.com/ThomasAribart/json-schema-to-ts/issues) 🤗\n\n## Table of content\n\n- [Installation](#installation)\n- [Use cases](#use-cases)\n  - [Const](#const)\n  - [Enums](#enums)\n  - [Primitive types](#primitive-types)\n  - [Nullable](#nullable)\n  - [Arrays](#arrays)\n  - [Tuples](#tuples)\n  - [Objects](#objects)\n- [Combining schemas](#combining-schemas)\n  - [AnyOf](#anyof)\n  - [AllOf](#allof)\n  - [OneOf](#oneof)\n  - [Not](#not)\n  - [If/Then/Else](#ifthenelse)\n  - [Definitions](#definitions)\n  - [References](#references)\n- [Deserialization](#deserialization)\n- [Extensions](#extensions)\n- [Typeguards](#typeguards)\n  - [Validators](#validators)\n  - [Compilers](#compilers)\n- [FAQ](#frequently-asked-questions)\n\n## Installation\n\n```bash\n# npm\nnpm install --save-dev json-schema-to-ts\n\n# yarn\nyarn add --dev json-schema-to-ts\n```\n\n> `json-schema-to-ts` requires TypeScript 4.3+. Using `strict` mode is required, as well as (apparently) turning off [`noStrictGenericChecks`](https://www.typescriptlang.org/tsconfig#noStrictGenericChecks).\n\n## Use cases\n\n### Const\n\n```typescript\nconst fooSchema = {\n  const: \"foo\",\n} as const;\n\ntype Foo = FromSchema<typeof fooSchema>;\n// => \"foo\"\n```\n\n### Enums\n\n```typescript\nconst enumSchema = {\n  enum: [true, 42, { foo: \"bar\" }],\n} as const;\n\ntype Enum = FromSchema<typeof enumSchema>;\n// => true | 42 | { foo: \"bar\"}\n```\n\nYou can also go full circle with typescript `enums`.\n\n```typescript\nenum Food {\n  Pizza = \"pizza\",\n  Taco = \"taco\",\n  Fries = \"fries\",\n}\n\nconst enumSchema = {\n  enum: Object.values(Food),\n} as const;\n\ntype Enum = FromSchema<typeof enumSchema>;\n// => Food\n```\n\n### Primitive types\n\n```typescript\nconst primitiveTypeSchema = {\n  type: \"null\", // \"boolean\", \"string\", \"integer\", \"number\"\n} as const;\n\ntype PrimitiveType = FromSchema<typeof primitiveTypeSchema>;\n// => null, boolean, string or number\n```\n\n```typescript\nconst primitiveTypesSchema = {\n  type: [\"null\", \"string\"],\n} as const;\n\ntype PrimitiveTypes = FromSchema<typeof primitiveTypesSchema>;\n// => null | string\n```\n\n> For more complex types, refinment keywords like `required` or `additionalItems` will apply 🙌\n\n### Nullable\n\n```typescript\nconst nullableSchema = {\n  type: \"string\",\n  nullable: true,\n} as const;\n\ntype Nullable = FromSchema<typeof nullableSchema>;\n// => string | null\n```\n\n### Arrays\n\n```typescript\nconst arraySchema = {\n  type: \"array\",\n  items: { type: \"string\" },\n} as const;\n\ntype Array = FromSchema<typeof arraySchema>;\n// => string[]\n```\n\n### Tuples\n\n```typescript\nconst tupleSchema = {\n  type: \"array\",\n  items: [{ type: \"boolean\" }, { type: \"string\" }],\n} as const;\n\ntype Tuple = FromSchema<typeof tupleSchema>;\n// => [] | [boolean] | [boolean, string] | [boolean, string, ...unknown[]]\n```\n\n`FromSchema` supports the `additionalItems` keyword:\n\n```typescript\nconst tupleSchema = {\n  type: \"array\",\n  items: [{ type: \"boolean\" }, { type: \"string\" }],\n  additionalItems: false,\n} as const;\n\ntype Tuple = FromSchema<typeof tupleSchema>;\n// => [] | [boolean] | [boolean, string]\n```\n\n```typescript\nconst tupleSchema = {\n  type: \"array\",\n  items: [{ type: \"boolean\" }, { type: \"string\" }],\n  additionalItems: { type: \"number\" },\n} as const;\n\ntype Tuple = FromSchema<typeof tupleSchema>;\n// => [] | [boolean] | [boolean, string] | [boolean, string, ...number[]]\n```\n\n...as well as the `minItems` and `maxItems` keywords:\n\n```typescript\nconst tupleSchema = {\n  type: \"array\",\n  items: [{ type: \"boolean\" }, { type: \"string\" }],\n  minItems: 1,\n  maxItems: 2,\n} as const;\n\ntype Tuple = FromSchema<typeof tupleSchema>;\n// => [boolean] | [boolean, string]\n```\n\n> Additional items will only work if Typescript's `strictNullChecks` option is activated\n\n### Objects\n\n```typescript\nconst objectSchema = {\n  type: \"object\",\n  properties: {\n    foo: { type: \"string\" },\n    bar: { type: \"number\" },\n  },\n  required: [\"foo\"],\n} as const;\n\ntype Object = FromSchema<typeof objectSchema>;\n// => { [x: string]: unknown; foo: string; bar?: number; }\n```\n\nDefaulted properties (even optional ones) will be set as required in the resulting type. You can turn off this behavior by setting the `keepDefaultedPropertiesOptional` option to `true`:\n\n```typescript\nconst defaultedProp = {\n  type: \"object\",\n  properties: {\n    foo: { type: \"string\", default: \"bar\" },\n  },\n  additionalProperties: false,\n} as const;\n\ntype Object = FromSchema<typeof defaultedProp>;\n// => { foo: string; }\n\ntype Object = FromSchema<\n  typeof defaultedProp,\n  { keepDefaultedPropertiesOptional: true }\n>;\n// => { foo?: string; }\n```\n\n`FromSchema` partially supports the `additionalProperties`, `patternProperties` and `unevaluatedProperties` keywords:\n\n- `additionalProperties` and `unevaluatedProperties` can be used to deny additional properties.\n\n```typescript\nconst closedObjectSchema = {\n  ...objectSchema,\n  additionalProperties: false,\n} as const;\n\ntype Object = FromSchema<typeof closedObjectSchema>;\n// => { foo: string; bar?: number; }\n```\n\n```typescript\nconst closedObjectSchema = {\n  type: \"object\",\n  allOf: [\n    {\n      properties: {\n        foo: { type: \"string\" },\n      },\n      required: [\"foo\"],\n    },\n    {\n      properties: {\n        bar: { type: \"number\" },\n      },\n    },\n  ],\n  unevaluatedProperties: false,\n} as const;\n\ntype Object = FromSchema<typeof closedObjectSchema>;\n// => { foo: string; bar?: number; }\n```\n\n- Used on their own, `additionalProperties` and/or `patternProperties` can be used to type unnamed properties.\n\n```typescript\nconst openObjectSchema = {\n  type: \"object\",\n  additionalProperties: {\n    type: \"boolean\",\n  },\n  patternProperties: {\n    \"^S\": { type: \"string\" },\n    \"^I\": { type: \"integer\" },\n  },\n} as const;\n\ntype Object = FromSchema<typeof openObjectSchema>;\n// => { [x: string]: string | number | boolean }\n```\n\nHowever:\n\n- When used in combination with the `properties` keyword, extra properties will always be typed as `unknown` to avoid conflicts.\n\n```typescript\nconst mixedObjectSchema = {\n  type: \"object\",\n  properties: {\n    foo: { enum: [\"bar\", \"baz\"] },\n  },\n  additionalProperties: { type: \"string\" },\n} as const;\n\ntype Object = FromSchema<typeof mixedObjectSchema>;\n// => { [x: string]: unknown; foo?: \"bar\" | \"baz\"; }\n```\n\n- Due to its context-dependent nature, `unevaluatedProperties` does not type extra-properties when used on its own. Use `additionalProperties` instead.\n\n```typescript\nconst openObjectSchema = {\n  type: \"object\",\n  unevaluatedProperties: {\n    type: \"boolean\",\n  },\n} as const;\n\ntype Object = FromSchema<typeof openObjectSchema>;\n// => { [x: string]: unknown }\n```\n\n## Combining schemas\n\n### AnyOf\n\n```typescript\nconst anyOfSchema = {\n  anyOf: [\n    { type: \"string\" },\n    {\n      type: \"array\",\n      items: { type: \"string\" },\n    },\n  ],\n} as const;\n\ntype AnyOf = FromSchema<typeof anyOfSchema>;\n// => string | string[]\n```\n\n`FromSchema` will correctly infer factored schemas:\n\n```typescript\nconst factoredSchema = {\n  type: \"object\",\n  properties: {\n    bool: { type: \"boolean\" },\n  },\n  required: [\"bool\"],\n  anyOf: [\n    {\n      properties: {\n        str: { type: \"string\" },\n      },\n      required: [\"str\"],\n    },\n    {\n      properties: {\n        num: { type: \"number\" },\n      },\n    },\n  ],\n} as const;\n\ntype Factored = FromSchema<typeof factoredSchema>;\n// => {\n//  [x:string]: unknown;\n//  bool: boolean;\n//  str: string;\n// } | {\n//  [x:string]: unknown;\n//  bool: boolean;\n//  num?: number;\n// }\n```\n\n### OneOf\n\n`FromSchema` will parse the `oneOf` keyword in the same way as `anyOf`:\n\n```typescript\nconst catSchema = {\n  type: \"object\",\n  oneOf: [\n    {\n      properties: {\n        name: { type: \"string\" },\n      },\n      required: [\"name\"],\n    },\n    {\n      properties: {\n        color: { enum: [\"black\", \"brown\", \"white\"] },\n      },\n    },\n  ],\n} as const;\n\ntype Cat = FromSchema<typeof catSchema>;\n// => {\n//  [x: string]: unknown;\n//  name: string;\n// } | {\n//  [x: string]: unknown;\n//  color?: \"black\" | \"brown\" | \"white\";\n// }\n\n// => Error will NOT be raised 😱\nconst invalidCat: Cat = { name: \"Garfield\" };\n```\n\n### AllOf\n\n```typescript\nconst addressSchema = {\n  type: \"object\",\n  allOf: [\n    {\n      properties: {\n        address: { type: \"string\" },\n        city: { type: \"string\" },\n        state: { type: \"string\" },\n      },\n      required: [\"address\", \"city\", \"state\"],\n    },\n    {\n      properties: {\n        type: { enum: [\"residential\", \"business\"] },\n      },\n    },\n  ],\n} as const;\n\ntype Address = FromSchema<typeof addressSchema>;\n// => {\n//   [x: string]: unknown;\n//   address: string;\n//   city: string;\n//   state: string;\n//   type?: \"residential\" | \"business\";\n// }\n```\n\n### Not\n\nExclusions require heavy computations, that can sometimes be aborted by Typescript and end up in `any` inferred types. For this reason, they are not activated by default: You can opt-in with the `parseNotKeyword` option.\n\n```typescript\nconst tupleSchema = {\n  type: \"array\",\n  items: [{ const: 1 }, { const: 2 }],\n  additionalItems: false,\n  not: {\n    const: [1],\n  },\n} as const;\n\ntype Tuple = FromSchema<typeof tupleSchema, { parseNotKeyword: true }>;\n// => [] | [1, 2]\n```\n\n```typescript\nconst primitiveTypeSchema = {\n  not: {\n    type: [\"array\", \"object\"],\n  },\n} as const;\n\ntype PrimitiveType = FromSchema<\n  typeof primitiveTypeSchema,\n  { parseNotKeyword: true }\n>;\n// => null | boolean | number | string\n```\n\nIn objects and tuples, the exclusion will propagate to properties/items if it can collapse on a single one.\n\n```typescript\n// 👍 Can be propagated on \"animal\" property\nconst petSchema = {\n  type: \"object\",\n  properties: {\n    animal: { enum: [\"cat\", \"dog\", \"boat\"] },\n  },\n  not: {\n    properties: { animal: { const: \"boat\" } },\n  },\n  required: [\"animal\"],\n  additionalProperties: false,\n} as const;\n\ntype Pet = FromSchema<typeof petSchema, { parseNotKeyword: true }>;\n// => { animal: \"cat\" | \"dog\" }\n```\n\n```typescript\n// ❌ Cannot be propagated\nconst petSchema = {\n  type: \"object\",\n  properties: {\n    animal: { enum: [\"cat\", \"dog\"] },\n    color: { enum: [\"black\", \"brown\", \"white\"] },\n  },\n  not: {\n    const: { animal: \"cat\", color: \"white\" },\n  },\n  required: [\"animal\", \"color\"],\n  additionalProperties: false,\n} as const;\n\ntype Pet = FromSchema<typeof petSchema, { parseNotKeyword: true }>;\n// => { animal: \"cat\" | \"dog\", color: \"black\" | \"brown\" | \"white\" }\n```\n\nAs some actionable keywords are not yet parsed, exclusions that resolve to `never` are granted the benefit of the doubt and omitted. For the moment, `FromSchema` assumes that you are not crafting unvalidatable exclusions.\n\n```typescript\nconst oddNumberSchema = {\n  type: \"number\",\n  not: { multipleOf: 2 },\n} as const;\n\ntype OddNumber = FromSchema<typeof oddNumberSchema, { parseNotKeyword: true }>;\n// => should and will resolve to \"number\"\n\nconst incorrectSchema = {\n  type: \"number\",\n  not: { bogus: \"option\" },\n} as const;\n\ntype Incorrect = FromSchema<typeof incorrectSchema, { parseNotKeyword: true }>;\n// => should resolve to \"never\" but will still resolve to \"number\"\n```\n\nAlso, keep in mind that TypeScript misses [refinment types](https://en.wikipedia.org/wiki/Refinement_type):\n\n```typescript\nconst goodLanguageSchema = {\n  type: \"string\",\n  not: {\n    enum: [\"Bummer\", \"Silly\", \"Lazy sod !\"],\n  },\n} as const;\n\ntype GoodLanguage = FromSchema<\n  typeof goodLanguageSchema,\n  { parseNotKeyword: true }\n>;\n// => string\n```\n\n### If/Then/Else\n\nFor the same reason as the `Not` keyword, conditions parsing is not activated by default: You can opt-in with the `parseIfThenElseKeywords` option.\n\n```typescript\nconst petSchema = {\n  type: \"object\",\n  properties: {\n    animal: { enum: [\"cat\", \"dog\"] },\n    dogBreed: { enum: Object.values(DogBreed) },\n    catBreed: { enum: Object.values(CatBreed) },\n  },\n  required: [\"animal\"],\n  if: {\n    properties: {\n      animal: { const: \"dog\" },\n    },\n  },\n  then: {\n    required: [\"dogBreed\"],\n    not: { required: [\"catBreed\"] },\n  },\n  else: {\n    required: [\"catBreed\"],\n    not: { required: [\"dogBreed\"] },\n  },\n  additionalProperties: false,\n} as const;\n\ntype Pet = FromSchema<typeof petSchema, { parseIfThenElseKeywords: true }>;\n// => {\n//  animal: \"dog\";\n//  dogBreed: DogBreed;\n//  catBreed?: CatBreed | undefined\n// } | {\n//  animal: \"cat\";\n//  catBreed: CatBreed;\n//  dogBreed?: DogBreed | undefined\n// }\n```\n\n> ☝️ `FromSchema` computes the resulting type as `(If ∩ Then) ∪ (¬If ∩ Else)`. While correct in theory, remember that the `not` keyword is not perfectly assimilated, which may become an issue in some complex schemas.\n\n### Definitions\n\n```typescript\nconst userSchema = {\n  type: \"object\",\n  properties: {\n    name: { $ref: \"#/definitions/name\" },\n    age: { $ref: \"#/definitions/age\" },\n  },\n  required: [\"name\", \"age\"],\n  additionalProperties: false,\n  definitions: {\n    name: { type: \"string\" },\n    age: { type: \"integer\" },\n  },\n} as const;\n\ntype User = FromSchema<typeof userSchema>;\n// => {\n//  name: string;\n//  age: number;\n// }\n```\n\n> ☝️ Wether in definitions or references, `FromSchema` will not work on recursive schemas for now.\n\n### References\n\nUnlike run-time validator classes like [AJV](https://github.com/ajv-validator/ajv), TS types cannot withhold internal states. Thus, they cannot keep any identified schemas in memory.\n\nBut you can hydrate them via the `references` option:\n\n```typescript\nconst userSchema = {\n  $id: \"http://example.com/schemas/user.json\",\n  type: \"object\",\n  properties: {\n    name: { type: \"string\" },\n    age: { type: \"integer\" },\n  },\n  required: [\"name\", \"age\"],\n  additionalProperties: false,\n} as const;\n\nconst usersSchema = {\n  type: \"array\",\n  items: {\n    $ref: \"http://example.com/schemas/user.json\",\n  },\n} as const;\n\ntype Users = FromSchema<\n  typeof usersSchema,\n  { references: [typeof userSchema] }\n>;\n// => {\n//  name: string;\n//  age: string;\n// }[]\n\nconst anotherUsersSchema = {\n  $id: \"http://example.com/schemas/users.json\",\n  type: \"array\",\n  items: { $ref: \"user.json\" },\n} as const;\n// => Will work as well 🙌\n```\n\n## Deserialization\n\nYou can specify deserialization patterns with the `deserialize` option:\n\n```typescript\nconst userSchema = {\n  type: \"object\",\n  properties: {\n    name: { type: \"string\" },\n    email: {\n      type: \"string\",\n      format: \"email\",\n    },\n    birthDate: {\n      type: \"string\",\n      format: \"date-time\",\n    },\n  },\n  required: [\"name\", \"email\", \"birthDate\"],\n  additionalProperties: false,\n} as const;\n\ntype Email = string & { brand: \"email\" };\n\ntype User = FromSchema<\n  typeof userSchema,\n  {\n    deserialize: [\n      {\n        pattern: {\n          type: \"string\";\n          format: \"email\";\n        };\n        output: Email;\n      },\n      {\n        pattern: {\n          type: \"string\";\n          format: \"date-time\";\n        };\n        output: Date;\n      },\n    ];\n  }\n>;\n// => {\n//  name: string;\n//  email: Email;\n//  birthDate: Date;\n// }\n```\n\n## Extensions\n\nIf you need to extend the JSON Schema spec with custom properties, use the `ExtendedJSONSchema` and `FromExtendedSchema` types to benefit from `json-schema-to-ts`:\n\n```typescript\nimport type { ExtendedJSONSchema, FromExtendedSchema } from \"json-schema-to-ts\";\n\ntype CustomProps = {\n  numberType: \"int\" | \"float\" | \"bigInt\";\n};\n\nconst bigIntSchema = {\n  type: \"number\",\n  numberType: \"bigInt\",\n  // 👇 Ensures mySchema is correct (includes extension)\n} as const satisfies ExtendedJSONSchema<CustomProps>;\n\ntype BigInt = FromExtendedSchema<\n  CustomProps,\n  typeof bigIntSchema,\n  {\n    // 👇 Works very well with the deserialize option!\n    deserialize: [\n      {\n        pattern: {\n          type: \"number\";\n          numberType: \"bigInt\";\n        };\n        output: bigint;\n      },\n    ];\n  }\n>;\n```\n\n## Typeguards\n\nYou can use `FromSchema` to implement your own typeguard:\n\n```typescript\nimport { FromSchema, Validator } from \"json-schema-to-ts\";\n\n// It's important to:\n// - Explicitely type your validator as Validator\n// - Use FromSchema as the default value of a 2nd generic first\nconst validate: Validator = <S extends JSONSchema, T = FromSchema<S>>(\n  schema: S,\n  data: unknown\n): data is T => {\n  const isDataValid: boolean = ... // Implement validation here\n  return isDataValid;\n};\n\nconst petSchema = { ... } as const\nlet data: unknown;\nif (validate(petSchema, data)) {\n  const { name, ... } = data; // data is typed as Pet 🙌\n}\n```\n\nIf needed, you can provide `FromSchema` options and additional validation options to the `Validator` type:\n\n```typescript\ntype FromSchemaOptions = { parseNotKeyword: true };\ntype ValidationOptions = [{ fastValidate: boolean }]\n\nconst validate: Validator<FromSchemaOptions, ValidationOptions> = <\n  S extends JSONSchema,\n  T = FromSchema<S, FromSchemaOptions>\n>(\n  schema: S,\n  data: unknown,\n  ...validationOptions: ValidationOptions\n): data is T => { ... };\n```\n\n`json-schema-to-ts` also exposes two helpers to write type guards. They don't impact the code that you wrote (they simply `return` it), but turn it into type guards.\n\nYou can use them to wrap either [`validators`](#validator) or [`compilers`](#compiler).\n\n### Validators\n\nA validator is a function that receives a schema plus some data, and returns `true` if the data is valid compared to the schema, `false` otherwise.\n\nYou can use the `wrapValidatorAsTypeGuard` helper to turn validators into type guards. Here is an implementation with [ajv](https://ajv.js.org/):\n\n```typescript\nimport Ajv from \"ajv\";\nimport { $Validator, wrapValidatorAsTypeGuard } from \"json-schema-to-ts\";\n\nconst ajv = new Ajv();\n\n// The initial validator definition is up to you\n// ($Validator is prefixed with $ to differ from resulting type guard)\nconst $validate: $Validator = (schema, data) => ajv.validate(schema, data);\n\nconst validate = wrapValidatorAsTypeGuard($validate);\n\nconst petSchema = { ... } as const;\n\nlet data: unknown;\nif (validate(petSchema, data)) {\n  const { name, ... } = data; // data is typed as Pet 🙌\n}\n```\n\nIf needed, you can provide `FromSchema` options and additional validation options as generic types:\n\n```typescript\ntype FromSchemaOptions = { parseNotKeyword: true };\ntype ValidationOptions = [{ fastValidate: boolean }]\n\nconst $validate: $Validator<ValidationOptions> = (\n  schema,\n  data,\n  ...validationOptions // typed as ValidationOptions\n) => { ... };\n\n// validate will inherit from ValidationOptions\nconst validate = wrapValidatorAsTypeGuard($validate);\n\n// with special FromSchemaOptions\n// (ValidationOptions needs to be re-provided)\nconst validate = wrapValidatorAsTypeGuard<\n  FromSchemaOptions,\n  ValidationOptions\n>($validate);\n```\n\n### Compilers\n\nA compiler is a function that takes a schema as an input and returns a data validator for this schema as an output.\n\nYou can use the `wrapCompilerAsTypeGuard` helper to turn compilers into type guard builders. Here is an implementation with [ajv](https://ajv.js.org/):\n\n```typescript\nimport Ajv from \"ajv\";\nimport { $Compiler, wrapCompilerAsTypeGuard } from \"json-schema-to-ts\";\n\n// The initial compiler definition is up to you\n// ($Compiler is prefixed with $ to differ from resulting type guard)\nconst $compile: $Compiler = (schema) => ajv.compile(schema);\n\nconst compile = wrapCompilerAsTypeGuard($compile);\n\nconst petSchema = { ... } as const;\n\nconst isPet = compile(petSchema);\n\nlet data: unknown;\nif (isPet(data)) {\n  const { name, ... } = data; // data is typed as Pet 🙌\n}\n```\n\nIf needed, you can provide `FromSchema` options, additional compiling and validation options as generic types:\n\n```typescript\ntype FromSchemaOptions = { parseNotKeyword: true };\ntype CompilingOptions = [{ fastCompile: boolean }];\ntype ValidationOptions = [{ fastValidate: boolean }];\n\nconst $compile: $Compiler<CompilingOptions, ValidationOptions> = (\n  schema,\n  ...compilingOptions // typed as CompilingOptions\n) => {\n  ...\n\n  return (\n    data,\n    ...validationOptions // typed as ValidationOptions\n  ) => { ...  };\n};\n\n// compile will inherit from all options\nconst compile = wrapCompilerAsTypeGuard($compile);\n\n// with special FromSchemaOptions\n// (options need to be re-provided)\nconst compile = wrapCompilerAsTypeGuard<\n  FromSchemaOptions,\n  CompilingOptions,\n  ValidationOptions\n>($compile);\n```\n\n## Frequently Asked Questions\n\n- [Does `json-schema-to-ts` work on _.json_ file schemas?](./documentation/FAQs/does-json-schema-to-ts-work-on-json-file-schemas.md)\n- [Will `json-schema-to-ts` impact the performances of my IDE/compiler?](./documentation/FAQs/will-json-schema-to-ts-impact-the-performances-of-my-ide-compiler.md)\n- [How can I apply `FromSchema` on generics?](./documentation/FAQs/applying-from-schema-on-generics.md)\n- [I get a `type instantiation is excessively deep and potentially infinite` error, what should I do?](./documentation/FAQs/i-get-a-type-instantiation-is-excessively-deep-and-potentially-infinite-error-what-should-i-do.md)\n","readmeFilename":"README.md"}