Luca Del Puppo - Senior Software Developer

Zod === TypeScript,
but at Runtime in Your React Applications

Luca Del Puppo

  • Senior Software Engineer
  • JavaScript enthusiast
  • TypeScript lover
  • “Youtuber”
  • “Writer”

Love sport: running, hiking

Love animals

Almost ten years ago

Interfaces

export interface CustomerModel {
  id: number;
  name: string;
  email: string;
  phone: string;
};

Types

export type CustomerModel = {
  id: number;
  name: string;
  email: string;
  phone: string;
};

Everything was perfect

Until

Hey, I'm a backend dev
and now I'll change the API

NaN

Unexpected string

NaN

Unexpected string

Hey, I'm Zod

Schema

import { z } from 'zod';

export const CustomerSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string(),
  phone: z.string(),
});

Convert to Type

import { TypeOf } from 'zod';

export type CustomerModel = TypeOf<typeof CustomerSchema>;

Parse

const customer = CustomerSchema.parse({
  id: 1,
  name: 'John Doe',
  email: 'email@email.com',
  phone: '123456789',
});

Something wrong

  • parse throws an exception
  • check ZodError error
    • issues
    • errors

Benefits

Validation
Layer

HTTP

socket

Help you with

some contracts

useParams


import { useParams } from "react-router-dom";

function OrderPage() {
    const { id } = useParams()
    // const id: string | undefined
 
    ...
}

useParamsTypeSafe

const OrderParamsSchema = z.object({
    id: z.coerce.number(),
})

function OrderPage() {
    const { id } = useParamsTypeSafe(OrderParamsSchema)
    // const id: number
 
    ...
}

useParamsTypeSafe

import { useParams } from 'react-router-dom';
import { ZodType, ZodTypeDef, z } from 'zod';

const useParamsTypeSafe = <Schema extends ZodType<Output, Def, Input>,
  Output,
  Def extends ZodTypeDef,
  Input
>(schema: Schema): z.infer<Schema> => {
  const params = useParams();
  return schema.parse(params)
};

export default useParamsTypeSafe

Who loves prop-types?

withZodValidation

import { ZodTypeAny, z } from 'zod';
import { validate } from '../zod/validation';

const withZodValidation =
  <Schema extends ZodTypeAny, P extends z.infer<Schema>>(schema: Schema) =>
    (Component: React.ComponentType<P>): React.FC<P> =>
      function ComponentWithValidation(props: P) {
        const realProps = schema.parse(props)

        return <Component {...realProps} />;
      };

export default withZodValidation

withZodValidation

const OrderPropsSchema = z.object({
    order: OrderSchema,
    onView: z.function().args(OrderSchema).returns(z.void()),
    onDelete: z.function().args(OrderSchema).returns(z.void()),
})

function Order(
	{ order, onView, onDelete }: z.infer<typeof OrderPropsSchema>
   ): ReactElement | null {
    ....
}

export default withZodValidation(OrderPropsSchema)(Order)

Demo

Conclusion

Conclusion

  • TypeScript is awesome, but with Zod a bit more 😎 
  • Create a validation layer between your app and the outside
    • Prevent execution of code with wrong data
    • Send you a notification if something goes wrong
  • You can guarantee the types both runtime and buildtime

Slides

Luca Del Puppo

@puppo92

Luca Del Puppo

Puppo_92

@puppo

Thank you!