Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

satisfies does not properly enforce enum on SomeJTDSchemaType #2206

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/json-type-definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,52 @@ const schema: JTDSchemaType<LinkedList, {node: LinkedList}> = {
`JTDSchemaType` currently validates 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.

## JTDDataType

The type `JTDDataType` can be used to transform a written schema to a type you can expect to be valid. 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 `JTDDataType` can verify are limited to the types that JTD can verify. If a type doesn't verify, `JTDDataType` 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 `JTDDataType`.

### Most Schemas

Most straightforward schemas should work with `JTDDataType`, e.g.

```typescript
const schema = {
properties: {
num: {type: "float64"},
nullableEnum: {enum: ["v1.0", "v1.2"], nullable: true},
values: {values: {type: "int32"}},
},
optionalProperties: {
optionalStr: {type: "string"},
},
} as const

type MyType = JTDDataType<typeof schema>
```

will compile. Using `MyType` with TypeScript will guarantee that AJV will accept it.

### Avoiding invalid schema

The validity of the schema can be enforced before converting it to a type to avoid having some stray `never` in the output type.

```typescript
const schema = {
properties: {
num: {type: "float64"},
nullableEnum: {enum: ["v1.0", "v1.2"], nullable: true},
values: {values: {type: "int32"}},
},
optionalProperties: {
optionalStr: {type: "string"},
},
} as const satisfies SomeJTDSchemaType

type MyType = JTDDataType<typeof schema>
```

Should a type in the schema be invalid, such as defining `{type: "float"}` instead of `{type: "float64"}`, TypeScript should refuse to compile instead of letting a `never` appear in `MyType`.

## Extending JTD

### Metadata schema member
Expand Down
2 changes: 1 addition & 1 deletion lib/types/jtd-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type SomeJTDSchemaType = (
// primitives
| {type: NumberType | StringType | "boolean"}
// enum
| {enum: string[]}
| {enum: readonly string[]}
// elements
| {elements: SomeJTDSchemaType}
// values
Expand Down