Luttez contre
l'any-gration à vos frontières !
@JoGrenat
@JoGrenat
Jordane Grenat
Les plus beaux endroits.
Les meilleures réunions.
npx comet-craft
- Appels réseau
- Local storage
- Base de données
- Formulaires
- Vous (any)
- ...
- json-schema
- joi
- yup
- zod
- io-ts
Parse, don't validate
Discriminated Unions
type Result =
| { type: 'success', data: MyData }
| { type: 'error', error: AnError }
const ResultSchema = z.discriminatedUnion('type', [
z.object({ type: z.literal('success'), data: MyDataSchema }),
z.object({ type: z.literal('error'), error: ErrorSchema }),
]);
Property-based testing
describe('createUser', () => {
it('should save user', () => {
const anyUser = ZodFastCheck().inputOf(UserSchema);
fc.assert(
fc.property(anyUser, (userInput) => {
await createUser(userInput);
const foundUser = await users.findByEmail(userInput.email);
expect(foundUser).toBeDefined();
})
);
});
});
Form-data
import { zfd } from "zod-form-data";
const schema = zfd.formData({
name: zfd.text(),
age: zfd.numeric(z.number().min(25).max(50)),
likesPizza: zfd.checkbox(),
});
export const action = async ({ request }) => {
const { name, age, likesPizza } = schema.parse(await request.formData());
};
tRPC
const appRouter = router({
getUserById: publicProcedure
.input(z.number())
.query(async (req) => {
const userId = req.input;
return findUser(userId);
}),
createUser: procedure
.input(UserCreationSchema)
.mutation(async (req) => {
const userToCreate = req.input;
const newUser = await createUser(userToCreate);
return newUser;
}),
});
export type AppRouter = typeof appRouter;
const user1 = await trpc.getUserById.query(1);
const createdUser = await trpc.createUser.mutate({
name: 'Jordane',
email: "jordane@devoxx.fr"
});
- Parse, don't validate
- Always check your borders
- Use value objects
Awesome article by Alexis King
Thank you!
@JoGrenat
- Parse, don't validate
- Always check your borders
- Use data objects
Awesome article by Alexis King
@JoGrenat
Zod :
By ereold
Zod :
- 519