Convert JSON Schema objects to TypeScript interfaces/types.
Defaulted Properties
By default, properties with a default value are treated as required in the resulting TypeScript type. To keep them optional, pass { keepDefaultedPropertiesOptional: true } as the second argument to FromSchema.
Controlling Additional Properties
- Deny extra properties: Use
additionalProperties: false or unevaluatedProperties: false (when used with allOf). - Type unnamed properties: Use
additionalProperties or patternProperties to define types for keys not explicitly listed in properties. - Conflict Resolution: If
properties is used alongside additionalProperties or patternProperties, extra properties are typed as unknown to prevent type conflicts. - Limitation:
unevaluatedProperties does not type extra properties when used on its own; use additionalProperties for that purpose.
// Basic Object
const objectSchema = {
type: "object",
properties: {
foo: { type: "string" },
bar: { type: "number" },
},
required: ["foo"],
} as const;
type Object = FromSchema<typeof objectSchema>;
// => { [x: string]: unknown; foo: string; bar?: number; }
// Handling Defaulted Properties
const defaultedProp = {
type: "object",
properties: {
foo: { type: "string", default: "bar" },
},
additionalProperties: false,
} as const;
// Default behavior: foo is required
type Object = FromSchema<typeof defaultedProp>;
// => { foo: string; }
// Custom behavior: foo is optional
type Object = FromSchema<
typeof defaultedProp,
{ keepDefaultedPropertiesOptional: true }
>;
// => { foo?: string; }
// Denying additional properties
const closedObjectSchema = {
...objectSchema,
additionalProperties: false,
} as const;
type Object = FromSchema<typeof closedObjectSchema>;
// => { foo: string; bar?: number; }
// Using unevaluatedProperties with allOf
const closedObjectSchema = {
type: "object",
allOf: [
{
properties: {
foo: { type: "string" },
},
required: ["foo"],
},
{
properties: {
bar: { type: "number" },
},
},
],
unevaluatedProperties: false,
} as const;
type Object = FromSchema<typeof closedObjectSchema>;
// => { foo: string; bar?: number; }
// Typing unnamed properties via patternProperties/additionalProperties
const openObjectSchema = {
type: "object",
additionalProperties: {
type: "boolean",
},
patternProperties: {
"^S": { type: "string" },
"^I": { type: "integer" },
},
} as const;
type Object = FromSchema<typeof openObjectSchema>;
// => { [x: string]: string | number | boolean }
// Conflict: properties + additionalProperties results in unknown for extras
const mixedObjectSchema = {
type: "object",
properties: {
foo: { enum: ["bar", "baz"] },
},
additionalProperties: { type: "string" },
} as const;
type Object = FromSchema<typeof mixedObjectSchema>;
// => { [x: string]: unknown; foo?: "bar" | "baz"; }