-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e496eff
commit 852b200
Showing
10 changed files
with
283 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
## [0.32.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.32.0) | ||
|
||
## Overview | ||
|
||
Revision 0.32.0 focuses primarily on enhancements to the Value module. It includes two new functions, Default and Clean which can be used for pre and post processing values before and after validation. It also includes a new namespace called ValueGuard which provides type safe guards for JavaScript primitive and object values. | ||
|
||
This revision also carries out updates to existing Value functions, and relaxes some of the rules around Types requiring type registration (limiting this requirement to only operations that type check during processing). Other updates include general refactoring and maintaince of existing Value functions. | ||
|
||
This revision contains no breaking changes. | ||
|
||
## Default | ||
|
||
Revision 0.32.0 adds a new Default function for preprocessing values prior to valdiation. This function accepts a schema + value, and will return a new value patched with any specified default values. This function works similar to Ajv's `useDefaults`, but is explicitly called rather than configured and does not mutate the original value. It works exclusively on the optional `default` schema annotation. | ||
|
||
The Default function makes a "best effort" attempt to patch values with defaults if it can, but respects any internal value passed on the original value except for `undefined`. This approach is intended to help ensure the caller passing an incorrect value is informed of the incorrect value post validation. | ||
|
||
The following shows usage and mapping behaviors. | ||
|
||
```typescript | ||
const T = Type.Object({ | ||
x: Type.Number({ default: 100 }), | ||
y: Type.Number({ default: 200 }) | ||
}, { | ||
default: {} | ||
}) | ||
|
||
Value.Default(T, undefined) // { x: 100, y: 200 } - undefined, use default {} into { x: 100, y: 200 } | ||
Value.Default(T, null) // null - (null respected) | ||
Value.Default(T, {}) // { x: 100, y: 200 } - empty {} into default x, y | ||
Value.Default(T, { x: 1 }) // { x: 1, y: 200 } - retain x, default y | ||
Value.Default(T, { x: 1, y: 2 }) // { x: 1, y: 2 } - retain x, y | ||
Value.Default(T, { x: 1, y: null }) // { x: 1, y: null } - retain x, y (null respected) | ||
``` | ||
The Default function performs no type checking at all and may return incomplete or incorrect values. Because of this, the Default function returns `unknown` and should be checked prior to use. Applications can setup a validation pipeline in the following way. | ||
```ts | ||
import { TSchema, Static, Type } from '@sinclair/typebox' | ||
|
||
function Parse<T extends TSchema>(schema: T, value: unknown): Static<T> { | ||
const withDefaults = Value.Default(schema, value) | ||
const valid = Value.Check(schema, withDefaults) | ||
if(!valid) throw new Error(Value.Errors(schema, withDefaults).First()!) | ||
return withDefaults | ||
} | ||
|
||
const A = Parse(Type.Object({ // const A = { x: 1, y: 0 } | ||
x: Type.Number({ default: 0 }), | ||
y: Type.Number({ default: 0 }), | ||
}), { x: 1 }) | ||
``` | ||
|
||
## Clean | ||
|
||
## ValueGuard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,47 @@ | ||
import { TypeSystem } from '@sinclair/typebox/system' | ||
import { TypeCompiler } from '@sinclair/typebox/compiler' | ||
import { Value, ValuePointer } from '@sinclair/typebox/value' | ||
import { Value, ValueGuard } from '@sinclair/typebox/value' | ||
import { Type, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox' | ||
|
||
// Todo: Investigate Union Default (initialize interior types) | ||
// Todo: Implement Value.Clean() Tests | ||
|
||
const T = Type.Record(Type.Number(), Type.String({ default: 1 }), { | ||
additionalProperties: Type.Any({ default: 1000 }), | ||
}) | ||
function Parse<T extends TSchema>(schema: T, value: unknown): Static<T> { | ||
const withDefaults = Value.Default(schema, value) | ||
const valid = Value.Check(schema, withDefaults) | ||
if (!valid) throw new Error(Value.Errors(schema, withDefaults).First()!.message) | ||
return withDefaults | ||
} | ||
|
||
export const Loose = Type.Object({ | ||
number: Type.Number(), | ||
negNumber: Type.Number(), | ||
maxNumber: Type.Number(), | ||
string: Type.String(), | ||
longString: Type.String(), | ||
boolean: Type.Boolean(), | ||
deeplyNested: Type.Object({ | ||
foo: Type.String(), | ||
num: Type.Number(), | ||
bool: Type.Boolean(), | ||
const A = Parse( | ||
Type.Object({ | ||
// const A = { x: 1, y: 0 } | ||
x: Type.Number({ default: 0 }), | ||
y: Type.Number({ default: 0 }), | ||
}), | ||
}) | ||
{ x: 1 }, | ||
) | ||
console.log(A) | ||
// const T = Type.Record(Type.Number(), Type.String({ default: 1 }), { | ||
// additionalProperties: Type.Any({ default: 1000 }), | ||
// }) | ||
|
||
const C = TypeCompiler.Compile(Loose) | ||
// export const Loose = Type.Object({ | ||
// number: Type.Number(), | ||
// negNumber: Type.Number(), | ||
// maxNumber: Type.Number(), | ||
// string: Type.String(), | ||
// longString: Type.String(), | ||
// boolean: Type.Boolean(), | ||
// deeplyNested: Type.Object({ | ||
// foo: Type.String(), | ||
// num: Type.Number(), | ||
// bool: Type.Boolean(), | ||
// }), | ||
// }) | ||
|
||
const A = Value.Create(Loose) | ||
// const C = TypeCompiler.Compile(Loose) | ||
|
||
let S = Date.now() | ||
for (let i = 0; i < 1_000_000; i++) { | ||
Value.Clean(Loose, A) | ||
} | ||
console.log(Date.now() - S) | ||
// const A = Value.Clone(new Map()) | ||
|
||
// console.log(A) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.