- Only a small subset of JSONschema is supported
- This library is very opinionated
- Probably don't use this in production
// Import various from-schema types
import { ArraySchema, EnumSchema, FromSchema, ObjectSchema } from 'from-schema';
// Import project-specific models defined elsewhere
import { attachment } from './attachment';
import { postBody } from './postBody';
import { postTitle } from './postTitle';
import { user } from './user';
// uuid can be passed to AJV for full UUID validation
export const uuid = {
type: 'string',
pattern:
'^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$',
} as const satisfies StringSchema;
// TypeScript will see Uuid as a standard string
export type Uuid = FromSchema<typeof uuid>;
/** Equivalent:
* type Uuid = string;
* */
// Define an EnumSchema for the post body type
export const bodyType = {
enum: ['plaintext', 'markdown'],
} as const satisfies EnumSchema;
// Export a type inferred from bodyType
export type BodyType = FromSchema<typeof bodyType>;
/** Equivalent:
* type BodyType = 'plaintext' | 'markdown'
* */
// Define an array of attachments (defined elsewhere)
export const attachments = {
type: 'array',
items: attachment,
} as const satisfies ArraySchema;
// Infer a type based on that model
export type Attachments = FromSchema<typeof attachments>;
/* Equivalent:
* type Attachments = {<external definition>}[];
* */
// Define the post itself -- AJV can compile this into a validator
export const post = {
description: 'A post containing text, images, or videos',
type: 'object',
properties: {
id: uuid, // You can embed schemas in other schemas
body: postBody, // Maybe this is a string with specific constraints?
bodyType,
groupId: uuid,
attachments,
authorId: user.properties.id, // You can model document relationships
likes: {
type: 'number',
},
publishDate: {
type: 'string',
},
replies: {
type: 'number',
},
title: postTitle, // Another string with constraints defined elsewhere
thread: {
type: 'array',
items: uuid,
},
},
required: [
'id',
'authorId',
'attachments',
'publishDate',
'likes',
'replies',
],
} as const satisfies ObjectSchema;
// Infer a TypeScript type
export type Post = FromSchema<typeof post>;
/** Equivalent:
* type Post = {
* id: string,
* body?: string,
* bodyType?: 'plaintest' | 'markdown'
* groupId?: string,
* attachments: {...}[],
* authorId: string,
* likes: number,
* publishDate: string,
* replies: number,
* title?: string,
* thread?: string[]
* }
* */
This section is experimental and may be removed in future.
Defined in ArraySchema.ts
.
export type ArraySchema = SchemaBase & {
readonly type: 'array';
readonly items: SchemaOrPrimitive;
readonly maxLength?: number;
readonly minLength?: number;
};
Represents an array schema. It extends the SchemaBase
and has the following properties:
type
: Must be'array'
.items
: The schema or primitive type for the array elements.maxLength
(optional): The maximum length of the array.minLength
(optional): The minimum length of the array.
Defined in BooleanSchema.ts
.
export type BooleanSchema = SchemaBase & {
readonly type: 'boolean';
};
Represents a boolean schema. It extends the SchemaBase
and has the following property:
type
: Must be'boolean'
.
Defined in EnumSchemaOf.ts
.
export type EnumSchemaOf<K> = SchemaBase & {
readonly enum: readonly K[];
};
Represents an enumeration schema of a specific type K
. It extends the SchemaBase
and has the following property:
enum
: An array of values of typeK
that the schema can take.
Defined in EnumSchema.ts
.
export type EnumSchema = SchemaBase & {
readonly enum: readonly (string | number | StringSchema | NumberSchema)[];
};
Represents an enumeration schema. It extends the SchemaBase
and has the following property:
enum
: An array of string, number,StringSchema
, orNumberSchema
values that the schema can take.
Defined in FromObjectSchema.ts
.
export type FromObjectSchema<T extends ObjectSchema> = OnlyRequired<T> &
OnlyOptional<T>;
A utility type that constructs an object type from an ObjectSchema
. It combines the required and optional properties of the schema.
Defined in FromPropertySchemas.ts
.
export type FromPropertySchemas<T extends ObjectSchema> = {
-readonly [K in keyof T['properties']]: PrimitiveOrFromSchema<
T['properties'][K]
>;
};
A utility type that constructs an object type from the properties
of an ObjectSchema
. It maps each property to its primitive or schema type.
Defined in FromSchema.ts
.
export type FromSchema<T> = T extends StringSchema
? string
: T extends NumberSchema
? number
: T extends BooleanSchema
? boolean
: T extends UnionSchemaOf<infer P extends SchemaOrPrimitive>
? PrimitiveOrFromSchema<P>
: T extends EnumSchemaOf<infer P extends SchemaOrPrimitive>
? PrimitiveOrFromSchema<P>
: T extends ObjectSchema
? FromObjectSchema<T>
: T extends MapSchema
? FromMapSchema<T>
: T extends ArraySchema
? FromSchema<T['items']>[]
: NoSchema;
A utility type that constructs a TypeScript type from a schema type. It recursively maps the schema types to their corresponding TypeScript types.
Defined in HttpRoute.ts
.
export type HttpRoute = SchemaBase & {
readonly request: ObjectSchema;
readonly response: ObjectSchema;
readonly authenticated: boolean;
};
Represents an HTTP route schema. It extends the SchemaBase
and has the following properties:
request
: AnObjectSchema
representing the request schema.response
: AnObjectSchema
representing the response schema.authenticated
: A boolean indicating if authentication is required for the route.
Defined in MapSchema.ts
.
export type MapSchema = {
readonly type: 'map';
readonly keys: StringSchema | EnumSchemaOf<string>;
readonly values: Schema;
readonly partial?: boolean;
};
Represents a map schema. It has the following properties:
type
: Must be'map'
.keys
: AStringSchema
orEnumSchemaOf<string>
representing the schema for the map keys.values
: The schema for the map values.partial
(optional): A boolean indicating if the map is partial (allows undefined values).
Defined in MapSchema.ts
.
export type MapSchemaOf<
K extends StringSchema | EnumSchemaOf<string>,
V,
P = false,
> = SchemaBase & {
readonly type: 'map';
readonly keys: K;
readonly values: V;
readonly partial: P;
};
Represents a map schema of specific key and value types. It extends the SchemaBase
and has the following properties:
type
: Must be'map'
.keys
: The schema for the map keys, of typeK
.values
: The schema or primitive type for the map values, of typeV
.partial
: A boolean indicating if the map is partial (allows undefined values), defaulting tofalse
.
Defined in MapSchema.ts
.
export type FromMapSchema<S extends MapSchema> = S['partial'] extends true
? {
-readonly [key in S['keys'] extends EnumSchemaOf<infer M extends string>
? M
: string]?: FromSchema<S['values']>;
}
: {
-readonly [key in S['keys'] extends EnumSchemaOf<infer M extends string>
? M
: string]: FromSchema<S['values']>;
};
A utility type that constructs a map type from a MapSchema
. It maps the key and value schemas to their corresponding TypeScript types, considering the partial
property.
Defined in NumberSchema.ts
.
export type NumberSchema = SchemaBase & {
readonly type: 'number' | 'integer';
readonly minimum?: number;
readonly maximum?: number;
};
Represents a number schema. It extends the SchemaBase
and has the following properties:
type
: Must be'number'
or'integer'
.minimum
(optional): The minimum value for the number.maximum
(optional): The maximum value for the number.
Defined in ObjectSchema.ts
.
export type ObjectSchemaWithoutRequired = SchemaBase & {
readonly type: 'object';
readonly properties: Record<string, SchemaOrPrimitive>;
readonly minProperties?: number;
readonly maxProperties?: number;
};
export type ObjectSchemaWithRequired = ObjectSchemaWithoutRequired & {
readonly required: readonly string[];
};
export type ObjectSchema =
| ObjectSchemaWithoutRequired
| ObjectSchemaWithRequired;
Represents an object schema. It extends the SchemaBase
and has the following properties:
type
: Must be'object'
.properties
: A record of property names and their corresponding schemas or primitive types.minProperties
(optional): The minimum number of properties required in the object.maxProperties
(optional): The maximum number of properties allowed in the object.required
(optional): An array of required property names.
Defined in OnlyOptional.ts
.
export type OnlyOptional<T extends ObjectSchema> =
T extends ObjectSchemaWithRequired
? Partial<Omit<FromPropertySchemas<T>, RequiredPropOf<T>>>
: Partial<T['properties']>;
A utility type that constructs an object type with only the optional properties of an ObjectSchema
.
Defined in OnlyRequired.ts
.
export type OnlyRequired<T extends ObjectSchema> =
T extends ObjectSchemaWithRequired
? Required<Pick<FromPropertySchemas<T>, RequiredPropOf<T>>>
: Record<string, never>;
A utility type that constructs an object type with only the required properties of an ObjectSchema
.
Defined in PrimitiveOrFromSchema.ts
.
export type PrimitiveOrFromSchema<T extends SchemaOrPrimitive> =
T extends Schema ? FromSchema<T> : T;
A utility type that constructs a TypeScript type from a schema or primitive type. If the input is a schema, it uses FromSchema
to convert it to a TypeScript type; otherwise, it returns the primitive type as is.
Defined in Primitive.ts
.
export type Primitive = string | number | boolean | string[];
Represents a primitive type, which can be a string, number, boolean, or an array of strings.
Defined in RequiredPropOf.ts
.
export type RequiredPropOf<T extends ObjectSchemaWithRequired> = Extract<
keyof T['properties'],
T['required'][number]
>;
A utility type that extracts the required property names from an ObjectSchemaWithRequired
.
Defined in SchemaBase.ts
.
export type SchemaBase = {
readonly description?: string;
};
Represents the base schema type. It has an optional description
property for providing a description of the schema.
Defined in SchemaOrPrimitive.ts
.
export type SchemaOrPrimitive = Schema | Primitive;
Represents a schema or primitive type.
Defined in Schema.ts
.
export type Schema =
| ArraySchema
| BooleanSchema
| EnumSchema
| MapSchema
| NumberSchema
| ObjectSchema
| StringSchema
| UnionSchema;
A union type representing all the available schema types.
Defined in StringSchema.ts
.
export type StringSchema = SchemaBase & {
readonly type: 'string';
readonly minLength?: number;
readonly maxLength?: number;
readonly pattern?: string;
readonly format?: string;
};
Represents a string schema. It extends the SchemaBase
and has the following properties:
type
: Must be'string'
.minLength
(optional): The minimum length of the string.maxLength
(optional): The maximum length of the string.pattern
(optional): A regular expression pattern that the string must match.format
(optional): A format specifier for the string (e.g., 'date', 'email').
Defined in UnionSchemaOf.ts
.
export type UnionSchemaOf<K extends SchemaOrPrimitive> = SchemaBase & {
readonly union: readonly K[];
};
Represents a union schema of a specific type K
. It extends the SchemaBase
and has the following property:
union
: An array of schemas or primitive types that the schema can take.
Defined in UnionSchema.ts
.
export type UnionSchema = SchemaBase & {
readonly union: readonly SchemaOrPrimitive[];
};
Represents a union schema. It extends the SchemaBase
and has the following property:
union
: An array of schemas or primitive types that the schema can take.
Defined in WebSocketRoute.ts
.
export type WebSocketRoute = SchemaBase & Record<string, never>;
Represents a WebSocket route schema. It extends the SchemaBase
and has no additional properties.
Here are some usage examples for the different schema types:
import { ArraySchema } from './ArraySchema';
const myArraySchema: ArraySchema = {
type: 'array',
items: {
type: 'string',
},
maxLength: 10,
minLength: 1,
};
import { BooleanSchema } from './BooleanSchema';
const myBooleanSchema: BooleanSchema = {
type: 'boolean',
};
import { EnumSchema } from './EnumSchema';
const myEnumSchema: EnumSchema = {
enum: ['red', 'green', 'blue'],
};
import { MapSchema } from './MapSchema';
const myMapSchema: MapSchema = {
type: 'map',
keys: {
type: 'string',
},
values: {
type: 'number',
},
partial: true,
};
import { NumberSchema } from './NumberSchema';
const myNumberSchema: NumberSchema = {
type: 'number',
minimum: 0,
maximum: 100,
};
import { ObjectSchema } from './ObjectSchema';
const myObjectSchema: ObjectSchema = {
type: 'object',
properties: {
name: {
type: 'string',
},
age: {
type: 'number',
},
},
required: ['name'],
};
import { StringSchema } from './StringSchema';
const myStringSchema: StringSchema = {
type: 'string',
minLength: 1,
maxLength: 50,
pattern: '^[A-Za-z]+$',
};
import { UnionSchema } from './UnionSchema';
const myUnionSchema: UnionSchema = {
union: [
{
type: 'string',
},
{
type: 'number',
},
],
};
Contributions to this project are welcome. If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the project's repository.
This project is licensed under the MIT License.