Skip to content

Commit

Permalink
Merge pull request #1457 from erikbrinkman/jtd-docs
Browse files Browse the repository at this point in the history
Documentation for JTDSchemaType
  • Loading branch information
epoberezkin committed Feb 23, 2021
2 parents 5a307d7 + 4df6e70 commit 2a27d13
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Expand Up @@ -274,6 +274,8 @@ if (validate(data)) {

With JSON Type Definition schema:

In JavaScript:

```javascript
const Ajv = require("ajv").default

Expand All @@ -292,6 +294,22 @@ const valid2 = validate({}) // false, foo is required
const valid3 = validate({foo: 1, bar: 2}) // false, bar is additional
```

In TypeScript:

```typescript
import {JTDSchemaType} from "ajv"

type MyData = {foo: number}

// Optional schema type annotation for schema to match MyData type.
// To use JTDSchemaType set `strictNullChecks: true` in tsconfig `compilerOptions`.
const schema: JTDSchemaType<MyData> = {
properties: {
foo: {type: "float64"},
},
}
```

See [this test](./spec/types/json-schema.spec.ts) for an advanced example, [API reference](./docs/api.md) and [Options](./docs/api.md#options) for more details.

Ajv compiles schemas to functions and caches them in all cases (using schema itself as a key for Map) or another function passed via options), so that the next time the same schema is used (not necessarily the same object instance) it won't be compiled again.
Expand Down
68 changes: 68 additions & 0 deletions docs/json-type-definition.md
Expand Up @@ -22,6 +22,7 @@ const ajv = new AjvJTD()
- [values](#values-schema-form) (for dictionary)
- [ref](#ref-schema-form) (to reference a schema in definitions)
- [empty](#empty-schema-form) (for any data)
- [JTDSchemaType](#jtdschematype)
- [Extending JTD](#extending-jtd)
- [metadata](#metadata-schema-member)
- [union](#union-keyword)
Expand Down Expand Up @@ -313,6 +314,73 @@ Unlike JSON Schema, JTD does not allow to reference:

Empty JTD schema defines the data instance that can be of any type, including JSON `null` (even if `nullable` member is not present). It cannot have any member other than `nullable` and `metadata`.

## JTDSchemaType

The type `JTDSchemaType` can be used to validate that the written schema matches the type you expect to validate. This type is strict such that if typescript compiles, you should require no further type guards. The downside of this is that the types that `JTDSchemaType` can verify are limited to the types that JTD can verify. If a type doesn't verify, `JTDSchemaType` should resolve to `never`, throwing an error when you try to assign to it. This means that types like `1 | 2 | 3`, or general untagged unions (outside of unions of string literals) cannot be used with `JTDSchemaType`.

### Most Schemas

Most straightforward types should work with `JTDSchemaType`, e.g.
```typescript
interface MyType {
num: number;
optionalStr?: string;
nullableEnum: "v1.0" | "v1.2" | null;
values: Record<string, number>;
}

const schema: JTDSchemaType<MyType> = {
properties: {
num: { type: "float64" },
nullableEnum: { enum: ["v1.0", "v1.2"], nullable: true },
values: { values: { type: "int32" } },
},
optionalProperties: {
optionalStr: { type: "string" },
}
}
```
will compile. Using `schema` with AJV will guarantee type safety.

### Ref Schemas

Ref schemas are a little more advanced, because the types of every definition must be specified in advance.
A simple ref schema is relatively straightforward:
```typescript
const schema: JTDSchemaType<{ val: number }, { num: number }> = {
definitions: {
num: { type: "float64" }
},
properties: {
val: { ref: "num" }
},
}
```
note that the type of all definitions was included as a second argument to `JTDSchemaType`.

This also works for recursive schemas:
```typescript
type LinkedList = { val: number, next?: LinkedList }
const schema: JTDSchemaType<LinkedList, { node: LinkedList }> = {
definitions: {
node: {
properties: {
val: { type: "float64" },
},
optionalProperties: {
next: { ref: "node" },
},
},
},
ref: "node",
}
```

### Notable Omissions

`JTDSchemaType` currently validats that if the schema compiles it will verify an accurate type, but there are a few places with potentially unexpected behavior.
`JTDSchemaType` doesn't verify the schema is correct. It won't reject schemas that definitions anywhere by the root, and it won't reject discriminator schemas that still define the descriminator in mapping properties. It also won't verify that enum schemas have every enum member as this isn't generally feasible in typescript yet.

## Extending JTD

### Metadata schema member
Expand Down

0 comments on commit 2a27d13

Please sign in to comment.