zod
Advanced tools
Comparing version 1.0.15 to 1.1.0
{ | ||
"name": "zod", | ||
"version": "1.0.15", | ||
"version": "1.1.0", | ||
"description": "TypeScript-first schema declaration and validation library with static type inference", | ||
@@ -45,6 +45,6 @@ "main": "./lib/index.js", | ||
"clean": "rm -rf lib/*", | ||
"build": "yarn run clean && tsc", | ||
"build": "yarn run clean && tsc --p tsconfig.package.json", | ||
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", | ||
"lint": "tslint -p tsconfig.json", | ||
"test": "jest --config jestconfig.json", | ||
"test": "jest --config jestconfig.json --coverage", | ||
"prepare": "npm run build", | ||
@@ -51,0 +51,0 @@ "play": "nodemon -e ts -w . -x ts-node src/playground.ts" |
@@ -6,2 +6,8 @@ <p align="center"> | ||
Created and maintained by [@vriad](https://twitter.com/vriad). | ||
The motivation for this library and a detailed comparison to various alternatives can be found at https://vriad.com/blog/zod. | ||
<br/> | ||
<br/> | ||
### Table of contents | ||
@@ -303,3 +309,3 @@ | ||
```ts | ||
const FishEnum = t.union([t.literal('Salmon'), t.literal('Tuna'), t.literal('Trout')]); | ||
const FishEnum = z.union([z.literal('Salmon'), z.literal('Tuna'), z.literal('Trout')]); | ||
@@ -313,10 +319,11 @@ FishEnum.parse('Salmon'); // => "Salmon" | ||
```ts | ||
const FishEnum = t.enum([t.literal('Salmon'), t.literal('Tuna'), t.literal('Trout')]); | ||
const FishEnum = z.enum(['Salmon', 'Tuna', 'Trout']); | ||
// you can autocomplete values | ||
// with the `.Values` variable | ||
// if you use `z.enum([ ... ])` | ||
// you can also autocomplete enum values | ||
// with the computed `.Values` property | ||
FishEnum.Values.Salmon; // => autocompletes | ||
FishEnum.Values; | ||
/* | ||
{ | ||
=> { | ||
Salmon: "Salmon", | ||
@@ -426,6 +433,32 @@ Tuna: "Tuna", | ||
Unfortunately this code is a bit duplicative, since you're declaring the types twice: once in the interface and again in the Zod definition. If your schema has lots of primitive fields, there's a way of reducing the amount of duplication: | ||
```ts | ||
// define all the non-recursive stuff here | ||
const BaseCategory = z.object({ | ||
name: z.string(), | ||
tags: z.array(z.string()), | ||
itemCount: z.number(), | ||
}); | ||
// create an interface that extends the base schema | ||
interface Category extends z.Infer<typeof BaseCategory> { | ||
subcategories: Category[]; | ||
} | ||
// merge the base schema with | ||
// a new Zod schema containing relations | ||
const Category: z.ZodType<Category> = BaseCategory.merge( | ||
z.object({ | ||
subcategories: z.lazy(() => z.array(Category)), | ||
}), | ||
); | ||
``` | ||
### Cyclical objects | ||
Validation still works as expected even when there are cycles in the data. | ||
```ts | ||
const untypedCategory: any = { | ||
const cyclicalCategory: any = { | ||
name: 'Category A', | ||
@@ -435,5 +468,5 @@ }; | ||
// creating a cycle | ||
untypedCategory.subcategories = [untypedCategory]; | ||
cyclicalCategory.subcategories = [cyclicalCategory]; | ||
const parsedCategory = Category.parse(untypedCategory); // parses successfully | ||
const parsedCategory = Category.parse(cyclicalCategory); // parses successfully | ||
@@ -454,2 +487,27 @@ parsedCategory.subcategories[0].subcategories[0].subcategories[0]; | ||
```ts | ||
const args = z.tuple([z.string()]); | ||
const returnType = z.number(); | ||
const myFunction = z.function(args, returnType); | ||
type myFunction = z.TypeOf<typeof myFunction>; | ||
// => (arg0: string)=>number | ||
``` | ||
`z.function` actually returns a higher-order "function factory". Every "factory" has `.implement()` method which accepts a function as input and returns a new function. | ||
```ts | ||
const myValidatedFunction = myFunction(x => { | ||
// TypeScript knows x is a string! | ||
return x.trim().length; | ||
}); | ||
``` | ||
`myValidatedFunction` now automatically validates both its inputs and return value against the schemas provided to `z.function`. If either is invalid, the function throws. | ||
This way you can confidently write application logic in a "validated function" without worrying about invalid inputs, scattering `schema.validate()` calls in your endpoint definitions,or writing duplicative types for your functions. | ||
Here's a more complex example showing how to write a typesafe API query endpoint: | ||
```ts | ||
const args = z.tuple([ | ||
@@ -467,13 +525,5 @@ z.object({ nameStartsWith: z.string() }), // filters | ||
const FetcherFactory = z.function(args, returnType); | ||
``` | ||
const FetcherEndpoint = z.function(args, returnType); | ||
`z.function` returns a higher-order "function factory". Every "factory" has `.validate()` method which accepts a function as input and returns a new function. The returned function automatically validates both its inputs and return value against the schemas provided to `z.function`. If either is invalid, the function throws. | ||
This way you can confidently execute business logic in a "validated function" without worrying about invalid inputs or return types, mixing your validation and business logic, or writing duplicative types for your functions. | ||
Here's an example. | ||
```ts | ||
const validatedQueryUser = FetchFunction.validate((filters, pagination) => { | ||
const searchUsers = FetcherEndpoint.validate((filters, pagination) => { | ||
// the arguments automatically have the appropriate types | ||
@@ -486,2 +536,6 @@ // as defined by the args tuple passed to `z.function()` | ||
const users = User.findAll({ | ||
// ... apply filters here | ||
}); | ||
// TypeScript statically verifies that value returned by | ||
@@ -493,3 +547,3 @@ // this function is of type { id: string; name: string; }[] | ||
const users = validatedQueryUser( | ||
const users = searchUsers( | ||
{ | ||
@@ -671,2 +725,4 @@ nameStartsWith: 'John', | ||
```ts | ||
import * as t from 'io-ts'; | ||
const A = t.type({ | ||
@@ -673,0 +729,0 @@ foo: t.string, |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
152158
82
2305
753
1