Skip to content

Commit

Permalink
Support Required Undefined Property Check (sinclairzx81#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 authored Feb 23, 2023
1 parent 5a520a1 commit 078cfac
Show file tree
Hide file tree
Showing 18 changed files with 493 additions and 243 deletions.
4 changes: 2 additions & 2 deletions benchmark/compression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export async function measure(test: string) {
const minified = statSync(`target/benchmark/compression/${test}.js`)
return {
test: test.padEnd(20),
compiled: `${Math.floor(compiled.size / 1000)} kb`.padStart(8),
minified: `${Math.floor(minified.size / 1000)} kb`.padStart(8),
compiled: `${(compiled.size / 1000).toFixed(1)} kb`.padStart(8),
minified: `${(minified.size / 1000).toFixed(1)} kb`.padStart(8),
ratio: compiled.size / minified.size,
}
}
Expand Down
3 changes: 3 additions & 0 deletions benchmark/compression/module/typebox-system.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TypeSystem } from '@sinclair/typebox/system'

TypeSystem.AllowNaN = true
11 changes: 11 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## [0.25.24](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.23)

Updates:

- [331](https://github.com/sinclairzx81/typebox/pull/331) Implements an additional check specific to property types of `required & undefined`. This to ensure the property key exists when the property value extends `undefined`.
- [331](https://github.com/sinclairzx81/typebox/pull/331) Documentation updates for Ajv and TypeCompiler

Additional:

- [331](https://github.com/sinclairzx81/typebox/pull/331) Remove unusued recursive code paths for create and cast.

## [0.25.23](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.23)

Updates:
Expand Down
66 changes: 39 additions & 27 deletions example/trpc/readme.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
# Using TypeBox with TRPC

To use TypeBox with TRPC, you will need to wrap types passed to procedures within a TRPC compatible assert function. Once wrapped, TypeBox can offer typical auto type inference for procedures, enhanced runtime checking performance and enable publishable procedure schematics based on the JSON Schema specification.
To use TypeBox with TRPC, you will need to wrap types passed to procedures within a TRPC compatible assertion function. Once wrapped, TypeBox can provide TRPC auto type inference for procedures, enhanced runtime checking performance and well as providing options for enabling publishable procedure schematics based on the JSON Schema specification.

## Contents

- [Example](#Example)
- [TypeCompiler](#TypeCompiler)
- [Value](#Value)
- [Ajv](#Ajv)
- [RpcType](#RpcType)
- [TypeCompiler](#TypeCompiler)
- [Value](#Value)
- [Ajv](#Ajv)

<a name="Example"></a>

## Example

The following example shows a minimal TypeBox TRPC setup with the `IoType` wrapper function described in the sections below.
The following shows a minimal TypeBox + TRPC setup with the `RpcType` wrapper function described in the sections below.

```typescript
import { Type } from '@sinclair/typebox'
import { initTRPC } from '@trpc/server'
import { IoType } from './io-type'
import { RpcType } from './rpctype'

const addInput = IoType(Type.Object({
a: Type.Number(),
b: Type.Number()
}))
const addInput = RpcType(
Type.Object({
a: Type.Number(),
b: Type.Number(),
}),
)

const addOutput = IoType(Type.Number())
const addOutput = RpcType(Type.Number())

const t = initTRPC.create()

export const appRouter = t.router({
add: t.procedure
.input(addInput)
.output(addOutput)
.query(({ input }) => input.a + input.b) // type-safe
.query(({ input }) => input.a + input.b), // type-safe
})
```

<a name="RpcType"></a>

## RpcType

Unlike Zod, Yup, Superstruct, TypeBox types are pure JSON Schema and do not implement built a in `parse` or `validate` function. Because of this, you will need to wrap the Type in a TRPC compatible function which implements `parse` or `validate` on behalf of TRPC. As JSON Schema is a formal specification, there are a number of ways you can choose to implement this function, the following shows recommended implementations.

<a name="TypeCompiler"></a>

## With [TypeCompiler](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKaB7AtAC4CeADvAHQEDOAUNKiTgE4GgDeoAKgMoDGAFvFTJQAX1CQmOVKADk4KtES9YyaE2DEyAIxwAPWXQbNWHTqXgBhaSTjwmYiVJnzFy1es0Xde4Lxt2TIb0jCzsXABKAAqWAKJMUg7iktJy4ARMJLzAVPYAbvaGNPB6oaz+iFSsAJI45mSgALygADycoCUESAAmVFx8gsIAfAAUVAJCyFicADSgTPCQ9ki88FTTA5MA2gC6TaC7AJRNQ+w0oKAVVZeCvADW+-VWAQhM5NYMdmMTwnMLSwtlGtDud5vACABXJiIUAjPLIWAQzCgCGIO6IHAAd0Qx0apwm93etzucIRSOOAH5QPDEfBQFgRiNcac2KCLldTKASMgCPw5ugqFRkABzOniZpbchSgl3cjxRJUUm0w47LYABh2bNAvKkmNAiHges40TiCWYIw4AqFoqwAAMACRsK0i+DJZigR3c3miW1zfzdZGyABCAEEACIAfQisQAigBVWLcTiyMQgi6iQ5MmiiGg0EAQGAIFDoLBSCFdN7UIxlcJKaAEY0xRwpFzpTLZXJMApBasmcJPZvONJuFRqDRaeA+YLGMIcWoD5JD2TkYC4QgWIoc0DIbrdaqIEjl-bziwjJ7kADy2gAVvBeAQLaCplwLOQAHIQ1DaexMmag7TTK+H5fj+IIZiCNBbju3QXuWh6sM0J5kGeQGft+TBMhBW4IdgiD1o2ljkLwCw8vAWbFKUfZQSQJARDg5b2PsBDkGWFaPhc0FYMxJBSKs3RQvAWrkEo8EjNB+7wWmFygOQ9EEKJ0GwfJ5ZSRc5AAI5IkwRCMhwIlHhmJy4fB5AiAA1MZ5bkNoxz5hOeBCks2aHEAA)
### With [TypeCompiler](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKATgBwMYAuAnrvAHSEDOAUNKrgPbaGgDeoAKgMr4AW8VMlABfUJGyNUoAOTgq0RPljJo2YCTIAjRgA8ZdBs1YdOpeAGEpuOPGyjxk6XIVKVajeZ27g+a7ewDeiYWdi4AJQAFCwBRbEl7MQkpWXBCPHxgKjsANzsDGnhdENZIAFclQmhGRFBwgjMyAB5OUCLCJAATKi5eASEAPgAKKn5BZCxOABoceEg7JHx4Kkm+8YBtAF1QAF5QLYBKdhpQUD9EKlYx-ABrXa5zKwYA8iebBBGxoRnsOYWlZYHE6zQhlbC1IY5ZCwMqYUAVG6IRgAd0QRx2A2Op1O0EgQ2uN1eAlukOhsIOR1+oPBoChMPgwNO50uYVwyEIfBm6CoVGQAHN4A49utyKKCeQ4gkqKT6QdNusAAybRmgDmSZGgRDwDWcKKxeLMIYcbm8gVYAAGABI2Cb+fAksxQNa2RyROaZn5OnCZAAhACCABEAPrhGIARQAqjFuJwZKIgacRDQkzQQBAYAgUOgsJIyh1sJRaMFjGFFNBCLrog5ks40hksrl8oYSmFGoKkk5Uq5lKp1Jp4N4gkZQhx6vg29XOzJyMAMv2CszWMhOp0AJKIXB5+5jttDNvkADyWgAVvAiEbgRMHmRyAA5MqoLR2IYHKbArSTcx3h9P7Av5MUjQNCLqAy6dAeeabqwew7uYe5fvej7PoBwE1Cy0GgGWFZ6uQ+C-Oy8D-oUxQliByC4Lg4SMHmdj3IQ5C5vmF6nGBWD0bgkhLJ0YIMtioDkIoUFDGB65QQm2LkNRhBCWBEHSXm4mnOQACOsLYMQQxGphG5biI6KYoJebkMIADU2lQeQWhHGm-YALS8vMAFAA)

The following uses the TypeCompiler to perform JIT optimized type checking for TRPC.

Expand All @@ -48,18 +57,19 @@ import { TSchema } from '@sinclair/typebox'
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { TRPCError } from '@trpc/server'

export const IoType = <T extends TSchema>(schema: T, references: TSchema[] = []) => {
export function RpcType<T extends TSchema>(schema: T, references: TSchema[] = []) {
const check = TypeCompiler.Compile(schema, references)
return (value: unknown) => check.Check(value) ? value : (() => {
return (value: unknown) => {
if (check.Check(value)) return value
const { path, message } = [...check.Errors(value)][0]
throw new TRPCError({ message: `${message} for ${path}`, code: 'BAD_REQUEST' })
})()
}
}
```

<a name="Value"></a>

## With [Value](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKaB7AtAC4CeADvAHQEDOAUNKiTgE4GgDeoAasrAK7ygAvqEhMcqUAHJwVaIgDGsZNCbBiZAEY4AHsABuPfpLoNmrDgBUAyvIAW8VMiEixE6bIVKVa0vC3bjekYWdlALACUABQBhAFEmMSZnUXEpcAImEnlgKngmPTzjGnhtYNZ5HEQqVgBJHAtfUABeUAAeC1ASgiQAEyowm3tHAD4ACio7B2QsCwAaUCZ4SDykeXgqGcGpgG0AXWbQPYBKZuHQGlBQUYM+TFBeRABrRBwAd0QTprPuW-Jo+3kj3Gk0c8xu-BOAH5QOCBFhRqNPmc2BdLqAKlVzKASMgCLZ5ugqFRkABzATCFrbcjUn78cjxRJUYFDZDzRbLRYKdZgwzwI67bYABl2qMueLEr1AiHgkoiMQZzFGHEJxLJWAABgASNgq0nwYSQZigbU4vGCdXzCo9O6SABCAEEACIAfXCsQAigBVWJWCySIRHVGCI6Img0EAQGAIFDoLBiXjdJiUWhBMyhOTQAhy6LJVxpDJZHJ5ApMQKmEKWRoGvPuOSKZSqdR+HRlsqhOoNMi51KScjAXCEXxFDHVUDIHo9GqIEgJg4d3yjTsUADyGgAVvB5AQlajpmFfOQAHK8VAaPKI2aojQzA-H0-nwPBwM0Eescc9ZcJmesFrzsiL28TzPJhEWfV9QB-bBEEzbNyHkRZcXgUNilKNNwOQEgSHCHAEzyA4CHIeNEx3S53ywAiSDENYel4RZRVAcg5G-UZ3ynb9AzRBicIIZj30-HiEw4tFyAAR34JgiARDgmNnYNTig79yCcABqBSE3IDQTgjJs8GJZYaGDIA)
### With [Value](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKATgBwMYAuAnrvAHSEDOAUNKrgPbaGgDeoAasrAK7ygAvqEjZGqUAHJwVaInyxk0bMBJkARowAewAG49+kug2asOAFQDK+ABbxUyISLETps+YuWrS8TVqP0TCzsoOYASgAKAMIAothi2E6i4lLghHj4wFTw2Lo5RjTwWkGskLzyhNCMiKBhBOY+ADzmoEWESAAmVKHWdg4AfAAUVLb2yFjmADQ48JA5SPjwVBO9YwDaALqgALygmwCU7DSgM4S82DWD+nyYoOUA1oiMAO6Ih9v9Rycn0JCD3DdyFE7Ph7sNRg5ptd+PtDth4GcLqBofBjt98NUqGZQLhkIQbNN0FQqMgAOYCYS7NbkGkA-jkOIJKjgvrIabwubw+RLKEGeD7DZrAAMGzRJ3xYmeoEQ8Cl4WijOYgw4RJJ5KwAAMACRsVVk+DCSDMUA63H4wQa6YYjq3SQAIQAggARAD6YRiAEUAKoxSzmSRCfZowQ0EM0EAQGAIFDoLBiXjtbCUWiBUwhOTQQjyqJJFypdIELI5PLYAImYIWHy5lJuOQKJQqNS+bRlkohOr4BpkauucjADJNgoYxBY0DIDodACSiFwCZ2tXqPkGXYoAHl1AAreBEZVo8ahHzkAByvFQ6hyg32kzR6gmh5PZ4vQcEsJoNGHo-HHVXCdnrF2HYrsu96nue2CXkG76Yqw-6gBmWaRFE5D4PCeLwJeb5FG2H6sMguC4GEjAJjk86EOQ8aJruJxflgZG4GIiwdOcqLfKA5ByH+gxftOf5Bqx5BEYQnFfj+QkJnx3zkAAjvw2DEIMypwTOc4vjsnwcQm5COAA1Epf7kOohwRk2AC0JJzKG+xAA)

The following performs dynamic type checking without code evaluation.

Expand All @@ -68,17 +78,18 @@ import { Value } from '@sinclair/typebox/value'
import { TSchema } from '@sinclair/typebox'
import { TRPCError } from '@trpc/server'

export const IoType = <T extends TSchema>(schema: T, references: TSchema[] = []) =>
(value: unknown) => Value.Check(schema, value) ? value : (() => {
export function RpcType<T extends TSchema>(schema: T, references: TSchema[] = []) {
return (value: unknown) => {
if (Value.Check(schema, value)) return value
const { path, message } = [...Value.Errors(schema, references, value)][0]
throw new TRPCError({ message: `${message} for ${path}`, code: 'BAD_REQUEST' })
})()
}
}
```

<a name="Ajv"></a>

## With [Ajv](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKaB7AtAC4CeADvAHQEDOAUNKiTgE4GgDeoAKgMoDGAFvFTIANKG4FkBaL1ABfUJCY5UoAOTgq0RL1jJoTYMTIAjHAA81dBs1YdOAJQAKAYQCiTZU3mLlqjQRMJLzAVPBMAG7hVvSMLKAAggBWEb4q6sgpwAAm0FQEwABMAAwlVjTw5nGsvDiI+aAAkjicpPCgALygADycoJUESNlUXHyCwgB8ABRUAkLIWJxiTPCQ4Ui88FSLY-MA2gC6naCHAJSdE+w0oKC19ayZqV2I8ADuiSlTp9egK2srOi25EgzDcyAEUz+60BF1Aj3IyGy2V2wkhq2hm1O3xudwac14AGtjvDagw4PAZnNhNjfvACABXJiIUBTCLIWD0zCgemIAmIHCvRCnLASKQyXqXDqXfEE1nsznnAD8oDZHPaWCmX1hbB+OLqDQ46CoVGQAHN4GJtPlkICnFJ+D4ujLyOEvFQAIR7YoHXWgAj8ZTvF7vRyuDxeKaGrYm81YUAAAwAJGwjTH4AoQd5k1bJLb7XJ42JatkuWoAEIJAAiAH0HG4AIoAVTc3E4ankNLkpy+NDkNBoIAgMAQKHQWGU9MGTEotFitnY2EQ0AIoZcPiU6QCQRCYUi0Ws1QXrTI6786k02l0+kMxngZksB-nHGax-aGbPanIwFwhDa5VxDxIo0iAkJOxwvm0UyvuQADyJhJPAvAEJGPwLFwbTkAAcvSqAmOEXwiD8JiLBh2G4fh3xdt8NAAXCSIwZOoGsF0EFkFBpE4XhTBfNRtHMYuy6ruQvArFIFLUZUh60cgJAkA4OCTuExwEOQE5TihNyItkWAqSQyibNkjLwL65DaExUxacBTE0jc5AKQQ5laQxDmTjZoDkAAjpyTBEJqHBmWBXawgFKnIKAADUi5MeQJjnIOt54Caay9qcQA)

### With [Ajv](https://www.typescriptlang.org/dev/bug-workbench/?target=99&lib=true&ts=4.7.4#code/PTAEAEDMEsBsFMB2BDAtvAXKATgBwMYAuAnrvAHSEDOAUNKrgPbaGgDeoAKgMr4AW8VMgA0oboWSFo+UAF9QkbI1SgA5OCrRE+WMmjZgJMgCNGAD1V0GzVh04AlAAoBhAKLYl2OQqUr1hPHxgKnhsADdQy3omFlAAQQArMJ9lNWQk4AATaCpCYAAmAAYiyxp4MxjWSABXbSlGRFB7Ak5SeAAeTlBywiRMqi5eASEAPgAKKn5BZCxOUWx4SFCkfHgqWaHpgG0AXVAAXlBdgEp2GlBQfAbc0HTkw8R4AHd4pLHj85xF5e018khmK5kPwxmMFksFr9TvsRrckuRkJlMpshGDvpDVscPhcrogblN8ABrA5wsLkK4MODwCZTITYr6EarYRpjMLIWDVTCgWqExCMJ6IY5YcSSaSdWEws4XC7QSBjAmE1nszlYhlMxpsjnwT44662UDoKhUZAAc3goi0uWQv0ckj43kOCvIoU8VAAhFtCjsdaBCHwlC9Hi8HC53J4xhxDcazVgAAYAEjYUdN8HkAK8ictEhtdtksdEV0yXNUACE4gARAD69lcAEUAKqubicVRyemyGgdmggCAwBAodBYJTVXrYSi0aI2digLTQQgh5zeRSpfyBYKhCLYKLWWJ2NpL3xqDRaHR6AxGeCmCxWSrT5r4VpkA8r8jAQIX0q4m6IzIASUQuAjiS96PtSoHkAA8sYCTwEQEafDMXBtOQABy1SoMYoTvMInzGLMyFoRhWEfLIWI0DQX6sD+EEjoBrCHCBbRjOBhGYdg7wfBReq+iSs7zk4zjkgskjUpx5S3pRty4Lg9iMCOoQkoQ5DDqO8EXD+WBKbgSirJkTLatKoDkFodFjD+-50fSFzkHJhCmdRtEjlZRkAI6ctgxCghwJlAaRBywj5SnIKAADUM4ASO5DGKcPYXgAtMaSydscQA)

The following uses Ajv to perform more generalized JSON Schema checks across the complete JSON Schema specification.

Expand All @@ -87,13 +98,14 @@ import { TSchema, Static } from '@sinclair/typebox'
import { TRPCError } from '@trpc/server'
import Ajv from 'ajv/dist/2020'

export const IoType = <T extends TSchema>(schema: T, references: TSchema[] = []) => {
export function RpcType<T extends TSchema>(schema: T, references: TSchema[] = []) {
const ajv = new Ajv()
references.forEach(reference => ajv.addSchema(reference))
references.forEach((reference) => ajv.addSchema(reference))
const check = ajv.compile(schema)
return (value: unknown): Static<T> => check(value) ? value : (() => {
return (value: unknown): Static<T> => {
if (check(value)) return value
const { message, instancePath } = check.errors![0]
throw new TRPCError({ message: `${message} for ${instancePath}`, code: 'BAD_REQUEST' })
})()
throw new TRPCError({ message: `${message} for ${instancePath}`, code: 'BAD_REQUEST' })
}
}
```
29 changes: 29 additions & 0 deletions example/typedef/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*--------------------------------------------------------------------------
@sinclair/typebox/extensions
The MIT License (MIT)
Copyright (c) 2017-2023 Haydn Paterson (sinclair) <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/

export * from './typedef'
100 changes: 100 additions & 0 deletions example/typedef/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# JSON Type Definition

JSON Type Definition (JTD) specification is an alternative schema specification to JSON Schema that provides better support for nominal type systems. TypeBox doesn't provide JTD support by default, but can be expressed through unsafe types and validated with Ajv.

This example provides a reference implementation for JSON Type Definition.

## TypeDef

Refer to the `typedef.ts` file in this directory for a reference implementation of the JSON Type Definition type builder.

```typescript
import { Static } from '@sinclair/typebox'
import { TypeDef } from './typedef'
```

## Properties

```typescript
// ------------------------------------------------------------------------
// PropertiesType
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/#properties-schemas
//
// ------------------------------------------------------------------------

export type PropertiesType = Static<typeof PropertiesType>
export const PropertiesType = TypeDef.Properties({
x: TypeDef.Float32(),
y: TypeDef.Float32(),
z: TypeDef.Float32(),
})
```

## Values

```typescript
// ------------------------------------------------------------------------
// ValuesType
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/#values-schemas
//
// ------------------------------------------------------------------------

export type ValuesType = Static<typeof ValuesType>
export const ValuesType = TypeDef.Values(TypeDef.Float64())
```

## Enum

```typescript
// ------------------------------------------------------------------------
// EnumType
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/#enum-schemas
//
// ------------------------------------------------------------------------

export type EnumType = Static<typeof EnumType>
export const EnumType = TypeDef.Enum(['FOO', 'BAR', 'BAZ'])
```

## Elements

```typescript
// ------------------------------------------------------------------------
// ElementsType
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/#elements-schemas
//
// ------------------------------------------------------------------------

export type ElementsType = Static<typeof ElementsType>
export const ElementsType = TypeDef.Elements(PropertiesType)
```

## Union

```typescript
// ------------------------------------------------------------------------
// UnionType
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/#discriminator-schemas
//
// ------------------------------------------------------------------------

export type UnionType = Static<typeof UnionType>
export const UnionType = TypeDef.Union('eventType', {
USER_CREATED: TypeDef.Properties({
id: TypeDef.String(),
}),
USER_PAYMENT_PLAN_CHANGED: TypeDef.Properties({
id: TypeDef.String(),
plan: TypeDef.Enum(['FREE', 'PAID']),
}),
USER_DELETED: TypeDef.Properties({
id: TypeDef.String(),
softDelete: TypeDef.Boolean(),
}),
})
```
88 changes: 88 additions & 0 deletions example/typedef/typedef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*--------------------------------------------------------------------------
@sinclair/typebox/typedef
The MIT License (MIT)
Copyright (c) 2017-2023 Haydn Paterson (sinclair) <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/

import { Type, Static, TUnsafe } from '@sinclair/typebox'

// ------------------------------------------------------------------------
// TypeDef Namespace
//
// https://jsontypedef.com/docs/jtd-in-5-minutes/
// ------------------------------------------------------------------------

export type StaticTypeDefUnion<D extends string, M extends Record<string, TUnsafe<any>>> = { [K in keyof M]: { [P in D]: K } & Static<M[K]> }[keyof M]

export namespace TypeDef {
export function Boolean() {
return Type.Unsafe<boolean>({ type: 'boolean' })
}
export function String() {
return Type.Unsafe<string>({ type: 'string' })
}
export function TimeStamp() {
return Type.Unsafe<string>({ type: 'timestamp' })
}
export function Float32() {
return Type.Unsafe<number>({ type: 'float32' })
}
export function Float64() {
return Type.Unsafe<number>({ type: 'float64' })
}
export function Int8() {
return Type.Unsafe<number>({ type: 'int8' })
}
export function Uint8() {
return Type.Unsafe<number>({ type: 'uint8' })
}
export function Int16() {
return Type.Unsafe<number>({ type: 'int16' })
}
export function Uint16() {
return Type.Unsafe<number>({ type: 'uint16' })
}
export function Int32() {
return Type.Unsafe<number>({ type: 'int32' })
}
export function Uint32() {
return Type.Unsafe<number>({ type: 'uint32' })
}
export function Enum<T extends string[]>(values: [...T]) {
return Type.Unsafe<T[number]>({ enum: values })
}
export function Elements<T extends TUnsafe<any>>(element: T) {
return Type.Unsafe<Array<Static<T>>>({ elements: element })
}
export function Properties<T extends Record<string, TUnsafe<any>>>(properties: T) {
return Type.Unsafe<{ [K in keyof T]: Static<T[K]> }>({ properties })
}
export function Values<V extends TUnsafe<any>>(values: V) {
return Type.Unsafe<Record<string, Static<V>>>({ values })
}
export function Union<D extends string, M extends Record<string, TUnsafe<any>>>(discriminator: D, mapping: M) {
return Type.Unsafe<StaticTypeDefUnion<D, M>>({ discriminator, mapping })
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sinclair/typebox",
"version": "0.25.23",
"version": "0.25.24",
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
Expand Down
Loading

0 comments on commit 078cfac

Please sign in to comment.