Installations
npm install json-schema-to-ts
Developer Guide
Typescript
Yes
Module System
CommonJS
Min. Node Version
>=16
Node Version
18.20.4
NPM Version
10.7.0
Score
99
Supply Chain
99.5
Quality
78.7
Maintenance
100
Vulnerability
100
License
Releases
Contributors
Unable to fetch Contributors
Languages
TypeScript (95.27%)
JavaScript (4.73%)
Developer
ThomasAribart
Download Statistics
Total Downloads
162,070,479
Last Day
348,389
Last Week
1,584,769
Last Month
6,359,428
Last Year
63,734,318
GitHub Statistics
1,515 Stars
394 Commits
31 Forks
9 Watching
4 Branches
7 Contributors
Bundle Size
794.00 B
Minified
382.00 B
Minified + Gzipped
Package Meta Information
Latest Version
3.1.1
Package Id
json-schema-to-ts@3.1.1
Unpacked Size
118.71 kB
Size
26.52 kB
File Count
267
NPM Version
10.7.0
Node Version
18.20.4
Publised On
29 Aug 2024
Total Downloads
Cumulative downloads
Total Downloads
162,070,479
Last day
13.9%
348,389
Compared to previous day
Last week
-1.7%
1,584,769
Compared to previous week
Last month
7.5%
6,359,428
Compared to previous month
Last year
105.4%
63,734,318
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
2
Dev Dependencies
36
💖 Huge thanks to the sponsors who help me maintain this repo:
Theodo | Your Brand Here |
Stop typing twice 🙅♂️
A lot of projects use JSON schemas for runtime data validation along with TypeScript for static type checking.
Their code may look like this:
1const dogSchema = { 2 type: "object", 3 properties: { 4 name: { type: "string" }, 5 age: { type: "integer" }, 6 hobbies: { type: "array", items: { type: "string" } }, 7 favoriteFood: { enum: ["pizza", "taco", "fries"] }, 8 }, 9 required: ["name", "age"], 10}; 11 12type Dog = { 13 name: string; 14 age: number; 15 hobbies?: string[]; 16 favoriteFood?: "pizza" | "taco" | "fries"; 17};
Both 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.
That's when json-schema-to-ts
comes to the rescue 💪
FromSchema
The FromSchema
method lets you infer TS types directly from JSON schemas:
1import { FromSchema } from "json-schema-to-ts"; 2 3const dogSchema = { 4 type: "object", 5 properties: { 6 name: { type: "string" }, 7 age: { type: "integer" }, 8 hobbies: { type: "array", items: { type: "string" } }, 9 favoriteFood: { enum: ["pizza", "taco", "fries"] }, 10 }, 11 required: ["name", "age"], 12} as const; 13 14type Dog = FromSchema<typeof dogSchema>; 15// => Will infer the same type as above
Schemas can even be nested, as long as you don't forget the as const
statement:
1const catSchema = { ... } as const; 2 3const petSchema = { 4 anyOf: [dogSchema, catSchema], 5} as const; 6 7type Pet = FromSchema<typeof petSchema>; 8// => Will work 🙌
The 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.
If you don't mind impacting the compiled code, you can use the asConst
util, which simply returns the schema while narrowing its inferred type.
1import { asConst } from "json-schema-to-ts"; 2 3const dogSchema = asConst({ 4 type: "object", 5 ... 6}); 7 8type Dog = FromSchema<typeof dogSchema>; 9// => Will work as well 🙌
Since TS 4.9, you can also use the satisfies
operator to benefit from type-checking and autocompletion:
1import type { JSONSchema } from "json-schema-to-ts"; 2 3const dogSchema = { 4 // Type-checked and autocompleted 🙌 5 type: "object" 6 ... 7} as const satisfies JSONSchema 8 9type Dog = FromSchema<typeof dogSchema> 10// => Still work 🙌
You can also use this with JSDocs by wrapping your schema in /** @type {const} @satisfies {import('json-schema-to-ts').JSONSchema} */ (...)
like:
const dogSchema = /** @type {const} @satisfies {import('json-schema-to-ts').JSONSchema} */ ({
// Type-checked and autocompleted 🙌
type: "object"
...
})
/** @type {import('json-schema-to-ts').FromSchema<typeof dogSchema>} */
const dog = { ... }
Why use json-schema-to-ts
?
If you're looking for runtime validation with added types, libraries like yup, zod or runtypes may suit your needs while being easier to use!
On the other hand, JSON schemas have the benefit of being widely used, more versatile and reusable (swaggers, APIaaS...).
If 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:
- ✅ Schema validation
FromSchema
raises TS errors on invalid schemas, based on DefinitelyTyped's definitions - ✨ No impact on compiled code:
json-schema-to-ts
only operates in type space. And after all, what's lighter than a dev-dependency? - 🍸 DRYness: Less code means less embarrassing typos
- 🤝 Real-time consistency: See that
string
that you used instead of anenum
? Or thisadditionalProperties
you confused withadditionalItems
? Or forgot entirely? Well,json-schema-to-ts
does! - 🔧 Reliability:
FromSchema
is extensively tested against AJV, and covers all the use cases that can be handled by TS for now* - 🏋️♂️ 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:
1const addressSchema = { 2 type: "object", 3 allOf: [ 4 { 5 properties: { 6 street: { type: "string" }, 7 city: { type: "string" }, 8 state: { type: "string" }, 9 }, 10 required: ["street", "city", "state"], 11 }, 12 { 13 properties: { 14 type: { enum: ["residential", "business"] }, 15 }, 16 }, 17 ], 18 additionalProperties: false, 19} as const;
But it is with FromSchema
!
1type Address = FromSchema<typeof addressSchema>; 2// => never 🙌
*If
json-schema-to-ts
misses one of your use case, feel free to open an issue 🤗
Table of content
Installation
1# npm 2npm install --save-dev json-schema-to-ts 3 4# yarn 5yarn add --dev json-schema-to-ts
json-schema-to-ts
requires TypeScript 4.3+. Usingstrict
mode is required, as well as (apparently) turning offnoStrictGenericChecks
.
Use cases
Const
1const fooSchema = { 2 const: "foo", 3} as const; 4 5type Foo = FromSchema<typeof fooSchema>; 6// => "foo"
Enums
1const enumSchema = { 2 enum: [true, 42, { foo: "bar" }], 3} as const; 4 5type Enum = FromSchema<typeof enumSchema>; 6// => true | 42 | { foo: "bar"}
You can also go full circle with typescript enums
.
1enum Food { 2 Pizza = "pizza", 3 Taco = "taco", 4 Fries = "fries", 5} 6 7const enumSchema = { 8 enum: Object.values(Food), 9} as const; 10 11type Enum = FromSchema<typeof enumSchema>; 12// => Food
Primitive types
1const primitiveTypeSchema = { 2 type: "null", // "boolean", "string", "integer", "number" 3} as const; 4 5type PrimitiveType = FromSchema<typeof primitiveTypeSchema>; 6// => null, boolean, string or number
1const primitiveTypesSchema = { 2 type: ["null", "string"], 3} as const; 4 5type PrimitiveTypes = FromSchema<typeof primitiveTypesSchema>; 6// => null | string
For more complex types, refinment keywords like
required
oradditionalItems
will apply 🙌
Nullable
1const nullableSchema = { 2 type: "string", 3 nullable: true, 4} as const; 5 6type Nullable = FromSchema<typeof nullableSchema>; 7// => string | null
Arrays
1const arraySchema = { 2 type: "array", 3 items: { type: "string" }, 4} as const; 5 6type Array = FromSchema<typeof arraySchema>; 7// => string[]
Tuples
1const tupleSchema = { 2 type: "array", 3 items: [{ type: "boolean" }, { type: "string" }], 4} as const; 5 6type Tuple = FromSchema<typeof tupleSchema>; 7// => [] | [boolean] | [boolean, string] | [boolean, string, ...unknown[]]
FromSchema
supports the additionalItems
keyword:
1const tupleSchema = { 2 type: "array", 3 items: [{ type: "boolean" }, { type: "string" }], 4 additionalItems: false, 5} as const; 6 7type Tuple = FromSchema<typeof tupleSchema>; 8// => [] | [boolean] | [boolean, string]
1const tupleSchema = { 2 type: "array", 3 items: [{ type: "boolean" }, { type: "string" }], 4 additionalItems: { type: "number" }, 5} as const; 6 7type Tuple = FromSchema<typeof tupleSchema>; 8// => [] | [boolean] | [boolean, string] | [boolean, string, ...number[]]
...as well as the minItems
and maxItems
keywords:
1const tupleSchema = { 2 type: "array", 3 items: [{ type: "boolean" }, { type: "string" }], 4 minItems: 1, 5 maxItems: 2, 6} as const; 7 8type Tuple = FromSchema<typeof tupleSchema>; 9// => [boolean] | [boolean, string]
Additional items will only work if Typescript's
strictNullChecks
option is activated
Objects
1const objectSchema = { 2 type: "object", 3 properties: { 4 foo: { type: "string" }, 5 bar: { type: "number" }, 6 }, 7 required: ["foo"], 8} as const; 9 10type Object = FromSchema<typeof objectSchema>; 11// => { [x: string]: unknown; foo: string; bar?: number; }
Defaulted 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
:
1const defaultedProp = { 2 type: "object", 3 properties: { 4 foo: { type: "string", default: "bar" }, 5 }, 6 additionalProperties: false, 7} as const; 8 9type Object = FromSchema<typeof defaultedProp>; 10// => { foo: string; } 11 12type Object = FromSchema< 13 typeof defaultedProp, 14 { keepDefaultedPropertiesOptional: true } 15>; 16// => { foo?: string; }
FromSchema
partially supports the additionalProperties
, patternProperties
and unevaluatedProperties
keywords:
additionalProperties
andunevaluatedProperties
can be used to deny additional properties.
1const closedObjectSchema = { 2 ...objectSchema, 3 additionalProperties: false, 4} as const; 5 6type Object = FromSchema<typeof closedObjectSchema>; 7// => { foo: string; bar?: number; }
1const closedObjectSchema = { 2 type: "object", 3 allOf: [ 4 { 5 properties: { 6 foo: { type: "string" }, 7 }, 8 required: ["foo"], 9 }, 10 { 11 properties: { 12 bar: { type: "number" }, 13 }, 14 }, 15 ], 16 unevaluatedProperties: false, 17} as const; 18 19type Object = FromSchema<typeof closedObjectSchema>; 20// => { foo: string; bar?: number; }
- Used on their own,
additionalProperties
and/orpatternProperties
can be used to type unnamed properties.
1const openObjectSchema = { 2 type: "object", 3 additionalProperties: { 4 type: "boolean", 5 }, 6 patternProperties: { 7 "^S": { type: "string" }, 8 "^I": { type: "integer" }, 9 }, 10} as const; 11 12type Object = FromSchema<typeof openObjectSchema>; 13// => { [x: string]: string | number | boolean }
However:
- When used in combination with the
properties
keyword, extra properties will always be typed asunknown
to avoid conflicts.
1const mixedObjectSchema = { 2 type: "object", 3 properties: { 4 foo: { enum: ["bar", "baz"] }, 5 }, 6 additionalProperties: { type: "string" }, 7} as const; 8 9type Object = FromSchema<typeof mixedObjectSchema>; 10// => { [x: string]: unknown; foo?: "bar" | "baz"; }
- Due to its context-dependent nature,
unevaluatedProperties
does not type extra-properties when used on its own. UseadditionalProperties
instead.
1const openObjectSchema = { 2 type: "object", 3 unevaluatedProperties: { 4 type: "boolean", 5 }, 6} as const; 7 8type Object = FromSchema<typeof openObjectSchema>; 9// => { [x: string]: unknown }
Combining schemas
AnyOf
1const anyOfSchema = { 2 anyOf: [ 3 { type: "string" }, 4 { 5 type: "array", 6 items: { type: "string" }, 7 }, 8 ], 9} as const; 10 11type AnyOf = FromSchema<typeof anyOfSchema>; 12// => string | string[]
FromSchema
will correctly infer factored schemas:
1const factoredSchema = { 2 type: "object", 3 properties: { 4 bool: { type: "boolean" }, 5 }, 6 required: ["bool"], 7 anyOf: [ 8 { 9 properties: { 10 str: { type: "string" }, 11 }, 12 required: ["str"], 13 }, 14 { 15 properties: { 16 num: { type: "number" }, 17 }, 18 }, 19 ], 20} as const; 21 22type Factored = FromSchema<typeof factoredSchema>; 23// => { 24// [x:string]: unknown; 25// bool: boolean; 26// str: string; 27// } | { 28// [x:string]: unknown; 29// bool: boolean; 30// num?: number; 31// }
OneOf
FromSchema
will parse the oneOf
keyword in the same way as anyOf
:
1const catSchema = { 2 type: "object", 3 oneOf: [ 4 { 5 properties: { 6 name: { type: "string" }, 7 }, 8 required: ["name"], 9 }, 10 { 11 properties: { 12 color: { enum: ["black", "brown", "white"] }, 13 }, 14 }, 15 ], 16} as const; 17 18type Cat = FromSchema<typeof catSchema>; 19// => { 20// [x: string]: unknown; 21// name: string; 22// } | { 23// [x: string]: unknown; 24// color?: "black" | "brown" | "white"; 25// } 26 27// => Error will NOT be raised 😱 28const invalidCat: Cat = { name: "Garfield" };
AllOf
1const addressSchema = { 2 type: "object", 3 allOf: [ 4 { 5 properties: { 6 address: { type: "string" }, 7 city: { type: "string" }, 8 state: { type: "string" }, 9 }, 10 required: ["address", "city", "state"], 11 }, 12 { 13 properties: { 14 type: { enum: ["residential", "business"] }, 15 }, 16 }, 17 ], 18} as const; 19 20type Address = FromSchema<typeof addressSchema>; 21// => { 22// [x: string]: unknown; 23// address: string; 24// city: string; 25// state: string; 26// type?: "residential" | "business"; 27// }
Not
Exclusions 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.
1const tupleSchema = { 2 type: "array", 3 items: [{ const: 1 }, { const: 2 }], 4 additionalItems: false, 5 not: { 6 const: [1], 7 }, 8} as const; 9 10type Tuple = FromSchema<typeof tupleSchema, { parseNotKeyword: true }>; 11// => [] | [1, 2]
1const primitiveTypeSchema = { 2 not: { 3 type: ["array", "object"], 4 }, 5} as const; 6 7type PrimitiveType = FromSchema< 8 typeof primitiveTypeSchema, 9 { parseNotKeyword: true } 10>; 11// => null | boolean | number | string
In objects and tuples, the exclusion will propagate to properties/items if it can collapse on a single one.
1// 👍 Can be propagated on "animal" property 2const petSchema = { 3 type: "object", 4 properties: { 5 animal: { enum: ["cat", "dog", "boat"] }, 6 }, 7 not: { 8 properties: { animal: { const: "boat" } }, 9 }, 10 required: ["animal"], 11 additionalProperties: false, 12} as const; 13 14type Pet = FromSchema<typeof petSchema, { parseNotKeyword: true }>; 15// => { animal: "cat" | "dog" }
1// ❌ Cannot be propagated 2const petSchema = { 3 type: "object", 4 properties: { 5 animal: { enum: ["cat", "dog"] }, 6 color: { enum: ["black", "brown", "white"] }, 7 }, 8 not: { 9 const: { animal: "cat", color: "white" }, 10 }, 11 required: ["animal", "color"], 12 additionalProperties: false, 13} as const; 14 15type Pet = FromSchema<typeof petSchema, { parseNotKeyword: true }>; 16// => { animal: "cat" | "dog", color: "black" | "brown" | "white" }
As 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.
1const oddNumberSchema = { 2 type: "number", 3 not: { multipleOf: 2 }, 4} as const; 5 6type OddNumber = FromSchema<typeof oddNumberSchema, { parseNotKeyword: true }>; 7// => should and will resolve to "number" 8 9const incorrectSchema = { 10 type: "number", 11 not: { bogus: "option" }, 12} as const; 13 14type Incorrect = FromSchema<typeof incorrectSchema, { parseNotKeyword: true }>; 15// => should resolve to "never" but will still resolve to "number"
Also, keep in mind that TypeScript misses refinment types:
1const goodLanguageSchema = { 2 type: "string", 3 not: { 4 enum: ["Bummer", "Silly", "Lazy sod !"], 5 }, 6} as const; 7 8type GoodLanguage = FromSchema< 9 typeof goodLanguageSchema, 10 { parseNotKeyword: true } 11>; 12// => string
If/Then/Else
For the same reason as the Not
keyword, conditions parsing is not activated by default: You can opt-in with the parseIfThenElseKeywords
option.
1const petSchema = { 2 type: "object", 3 properties: { 4 animal: { enum: ["cat", "dog"] }, 5 dogBreed: { enum: Object.values(DogBreed) }, 6 catBreed: { enum: Object.values(CatBreed) }, 7 }, 8 required: ["animal"], 9 if: { 10 properties: { 11 animal: { const: "dog" }, 12 }, 13 }, 14 then: { 15 required: ["dogBreed"], 16 not: { required: ["catBreed"] }, 17 }, 18 else: { 19 required: ["catBreed"], 20 not: { required: ["dogBreed"] }, 21 }, 22 additionalProperties: false, 23} as const; 24 25type Pet = FromSchema<typeof petSchema, { parseIfThenElseKeywords: true }>; 26// => { 27// animal: "dog"; 28// dogBreed: DogBreed; 29// catBreed?: CatBreed | undefined 30// } | { 31// animal: "cat"; 32// catBreed: CatBreed; 33// dogBreed?: DogBreed | undefined 34// }
☝️
FromSchema
computes the resulting type as(If ∩ Then) ∪ (¬If ∩ Else)
. While correct in theory, remember that thenot
keyword is not perfectly assimilated, which may become an issue in some complex schemas.
Definitions
1const userSchema = { 2 type: "object", 3 properties: { 4 name: { $ref: "#/definitions/name" }, 5 age: { $ref: "#/definitions/age" }, 6 }, 7 required: ["name", "age"], 8 additionalProperties: false, 9 definitions: { 10 name: { type: "string" }, 11 age: { type: "integer" }, 12 }, 13} as const; 14 15type User = FromSchema<typeof userSchema>; 16// => { 17// name: string; 18// age: number; 19// }
☝️ Wether in definitions or references,
FromSchema
will not work on recursive schemas for now.
References
Unlike run-time validator classes like AJV, TS types cannot withhold internal states. Thus, they cannot keep any identified schemas in memory.
But you can hydrate them via the references
option:
1const userSchema = { 2 $id: "http://example.com/schemas/user.json", 3 type: "object", 4 properties: { 5 name: { type: "string" }, 6 age: { type: "integer" }, 7 }, 8 required: ["name", "age"], 9 additionalProperties: false, 10} as const; 11 12const usersSchema = { 13 type: "array", 14 items: { 15 $ref: "http://example.com/schemas/user.json", 16 }, 17} as const; 18 19type Users = FromSchema< 20 typeof usersSchema, 21 { references: [typeof userSchema] } 22>; 23// => { 24// name: string; 25// age: string; 26// }[] 27 28const anotherUsersSchema = { 29 $id: "http://example.com/schemas/users.json", 30 type: "array", 31 items: { $ref: "user.json" }, 32} as const; 33// => Will work as well 🙌
Deserialization
You can specify deserialization patterns with the deserialize
option:
1const userSchema = { 2 type: "object", 3 properties: { 4 name: { type: "string" }, 5 email: { 6 type: "string", 7 format: "email", 8 }, 9 birthDate: { 10 type: "string", 11 format: "date-time", 12 }, 13 }, 14 required: ["name", "email", "birthDate"], 15 additionalProperties: false, 16} as const; 17 18type Email = string & { brand: "email" }; 19 20type User = FromSchema< 21 typeof userSchema, 22 { 23 deserialize: [ 24 { 25 pattern: { 26 type: "string"; 27 format: "email"; 28 }; 29 output: Email; 30 }, 31 { 32 pattern: { 33 type: "string"; 34 format: "date-time"; 35 }; 36 output: Date; 37 }, 38 ]; 39 } 40>; 41// => { 42// name: string; 43// email: Email; 44// birthDate: Date; 45// }
Extensions
If you need to extend the JSON Schema spec with custom properties, use the ExtendedJSONSchema
and FromExtendedSchema
types to benefit from json-schema-to-ts
:
1import type { ExtendedJSONSchema, FromExtendedSchema } from "json-schema-to-ts"; 2 3type CustomProps = { 4 numberType: "int" | "float" | "bigInt"; 5}; 6 7const bigIntSchema = { 8 type: "number", 9 numberType: "bigInt", 10 // 👇 Ensures mySchema is correct (includes extension) 11} as const satisfies ExtendedJSONSchema<CustomProps>; 12 13type BigInt = FromExtendedSchema< 14 CustomProps, 15 typeof bigIntSchema, 16 { 17 // 👇 Works very well with the deserialize option! 18 deserialize: [ 19 { 20 pattern: { 21 type: "number"; 22 numberType: "bigInt"; 23 }; 24 output: bigint; 25 }, 26 ]; 27 } 28>;
Typeguards
You can use FromSchema
to implement your own typeguard:
1import { FromSchema, Validator } from "json-schema-to-ts"; 2 3// It's important to: 4// - Explicitely type your validator as Validator 5// - Use FromSchema as the default value of a 2nd generic first 6const validate: Validator = <S extends JSONSchema, T = FromSchema<S>>( 7 schema: S, 8 data: unknown 9): data is T => { 10 const isDataValid: boolean = ... // Implement validation here 11 return isDataValid; 12}; 13 14const petSchema = { ... } as const 15let data: unknown; 16if (validate(petSchema, data)) { 17 const { name, ... } = data; // data is typed as Pet 🙌 18}
If needed, you can provide FromSchema
options and additional validation options to the Validator
type:
1type FromSchemaOptions = { parseNotKeyword: true }; 2type ValidationOptions = [{ fastValidate: boolean }] 3 4const validate: Validator<FromSchemaOptions, ValidationOptions> = < 5 S extends JSONSchema, 6 T = FromSchema<S, FromSchemaOptions> 7>( 8 schema: S, 9 data: unknown, 10 ...validationOptions: ValidationOptions 11): data is T => { ... };
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.
You can use them to wrap either validators
or compilers
.
Validators
A 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.
You can use the wrapValidatorAsTypeGuard
helper to turn validators into type guards. Here is an implementation with ajv:
1import Ajv from "ajv"; 2import { $Validator, wrapValidatorAsTypeGuard } from "json-schema-to-ts"; 3 4const ajv = new Ajv(); 5 6// The initial validator definition is up to you 7// ($Validator is prefixed with $ to differ from resulting type guard) 8const $validate: $Validator = (schema, data) => ajv.validate(schema, data); 9 10const validate = wrapValidatorAsTypeGuard($validate); 11 12const petSchema = { ... } as const; 13 14let data: unknown; 15if (validate(petSchema, data)) { 16 const { name, ... } = data; // data is typed as Pet 🙌 17}
If needed, you can provide FromSchema
options and additional validation options as generic types:
1type FromSchemaOptions = { parseNotKeyword: true }; 2type ValidationOptions = [{ fastValidate: boolean }] 3 4const $validate: $Validator<ValidationOptions> = ( 5 schema, 6 data, 7 ...validationOptions // typed as ValidationOptions 8) => { ... }; 9 10// validate will inherit from ValidationOptions 11const validate = wrapValidatorAsTypeGuard($validate); 12 13// with special FromSchemaOptions 14// (ValidationOptions needs to be re-provided) 15const validate = wrapValidatorAsTypeGuard< 16 FromSchemaOptions, 17 ValidationOptions 18>($validate);
Compilers
A compiler is a function that takes a schema as an input and returns a data validator for this schema as an output.
You can use the wrapCompilerAsTypeGuard
helper to turn compilers into type guard builders. Here is an implementation with ajv:
1import Ajv from "ajv"; 2import { $Compiler, wrapCompilerAsTypeGuard } from "json-schema-to-ts"; 3 4// The initial compiler definition is up to you 5// ($Compiler is prefixed with $ to differ from resulting type guard) 6const $compile: $Compiler = (schema) => ajv.compile(schema); 7 8const compile = wrapCompilerAsTypeGuard($compile); 9 10const petSchema = { ... } as const; 11 12const isPet = compile(petSchema); 13 14let data: unknown; 15if (isPet(data)) { 16 const { name, ... } = data; // data is typed as Pet 🙌 17}
If needed, you can provide FromSchema
options, additional compiling and validation options as generic types:
1type FromSchemaOptions = { parseNotKeyword: true }; 2type CompilingOptions = [{ fastCompile: boolean }]; 3type ValidationOptions = [{ fastValidate: boolean }]; 4 5const $compile: $Compiler<CompilingOptions, ValidationOptions> = ( 6 schema, 7 ...compilingOptions // typed as CompilingOptions 8) => { 9 ... 10 11 return ( 12 data, 13 ...validationOptions // typed as ValidationOptions 14 ) => { ... }; 15}; 16 17// compile will inherit from all options 18const compile = wrapCompilerAsTypeGuard($compile); 19 20// with special FromSchemaOptions 21// (options need to be re-provided) 22const compile = wrapCompilerAsTypeGuard< 23 FromSchemaOptions, 24 CompilingOptions, 25 ValidationOptions 26>($compile);
Frequently Asked Questions
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
Reason
9 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Reason
Found 1/18 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/draft-or-update-next-release.yml:1
- Warn: no topLevel permission defined: .github/workflows/release.yml:1
- Warn: topLevel 'contents' permission set to 'write': .github/workflows/sync-readme-sponsors.yml:9
- Warn: no topLevel permission defined: .github/workflows/test-pr.yml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/draft-or-update-next-release.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/draft-or-update-next-release.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/draft-or-update-next-release.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/draft-or-update-next-release.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/release.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/release.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/release.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/release.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sync-readme-sponsors.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/sync-readme-sponsors.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/sync-readme-sponsors.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/sync-readme-sponsors.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/sync-readme-sponsors.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/sync-readme-sponsors.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-pr.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/ThomasAribart/json-schema-to-ts/test-pr.yml/main?enable=pin
- Info: 0 out of 5 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 5 third-party GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 22 are checked with a SAST tool
Score
3
/10
Last Scanned on 2025-01-27
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to json-schema-to-ts
ts-to-json
Generate JSON schema from your Typescript sources
@fastify/type-provider-json-schema-to-ts
A Type Provider for json-schema-to-ts over Fastify
@krimzen-ninja/json-schema-to-ts
Helper library for translating between TS and JSON schema, allowing you to define your objects once
@castore/json-schema-event
DRY Castore EventType definition using JSON Schemas and json-schema-to-ts