Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Zod: Levando a validação de dados a um novo nível.

Zod: Levando a validação de dados a um novo nível.

Typescript vem se tornando um padrão pra qualquer projeto bem estruturado hoje em dia, as validações de dados tem caído no gosto das pessoas desenvolvedoras e com o Zod nós levamos isso a um novo nível, ele é um validador de dados baseado em schema que vai facilitar a sua vida.

Gefy Marcos

June 12, 2023
Tweet

More Decks by Gefy Marcos

Other Decks in Programming

Transcript

  1. @gefymarcos • Garantir o tipo de um dado. Por que

    a validação de dados é importante?
  2. @gefymarcos • Garantir o tipo de um dado. • Garantir

    que campos obrigatórios sejam preenchidos. Por que a validação de dados é importante?
  3. @gefymarcos • Garantir o tipo de um dado. • Garantir

    que campos obrigatórios sejam preenchidos. • Verificar se todos os formatos estão corretos. Por que a validação de dados é importante?
  4. @gefymarcos • Garantir o tipo de um dado. • Garantir

    que campos obrigatórios sejam preenchidos. • Verificar se todos os formatos estão corretos. • Limitar faixa de valores. Por que a validação de dados é importante?
  5. @gefymarcos • Garantir o tipo de um dado. • Garantir

    que campos obrigatórios sejam preenchidos. • Verificar se todos os formatos estão corretos. • Limitar faixa de valores. • Garantir a integridade dos modelos de dados. Por que a validação de dados é importante?
  6. @gefymarcos • Definição de esquema de validação declarativo. • Validação

    condicional. • Composição de esquemas. • Personalização de mensagens de erros. Principais recursos • Definição de esquema de validação declarativo.
  7. @gefymarcos • Definição de esquema de validação declarativo. • Validação

    condicional. • Composição de esquemas. • Personalização de mensagens de erros. Principais recursos • Validação condicional.
  8. @gefymarcos • Definição de esquema de validação declarativo. • Validação

    condicional. • Composição de esquemas. • Personalização de mensagens de erros. Principais recursos • Composição de esquemas.
  9. @gefymarcos • Definição de esquema de validação declarativo. • Validação

    condicional. • Composição de esquemas. • Personalização de mensagens de erros. Principais recursos • Personalização de mensagens de erros.
  10. @gefymarcos Validação de strings import { z } from "zod";

    const exampleSchema = z.string().min(5).max(10);
  11. @gefymarcos Validação de strings import { z } from "zod";

    const exampleSchema = z.string().min(5).max(10);
  12. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); const exampleSchema = z.string().min(5).max(10);
  13. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); ✅ => Hello const exampleSchema = z.string().min(5).max(10);
  14. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); exampleSchema.parse("Hi"); ✅ => Hello const exampleSchema = z.string().min(5).max(10);
  15. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); exampleSchema.parse("Hi"); ✅ => Hello ⛔ => Input is too short const exampleSchema = z.string().min(5).max(10);
  16. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); exampleSchema.parse("Hi"); exampleSchema.parse(“Hello hello”); ✅ => Hello ⛔ => Input is too short const exampleSchema = z.string().min(5).max(10);
  17. @gefymarcos Validação de strings import { z } from "zod";

    exampleSchema.parse("Hello"); exampleSchema.parse("Hi"); exampleSchema.parse(“Hello hello”); ✅ => Hello ⛔ => Input is too short ⛔ => Input is too long const exampleSchema = z.string().min(5).max(10);
  18. @gefymarcos Validação de numbers import { z } from "zod";

    const exampleSchema = z.number().positive();
  19. @gefymarcos import { z } from "zod"; Validação de numbers

    const exampleSchema = z.number().positive();
  20. @gefymarcos import { z } from "zod"; Validação de numbers

    exampleSchema.parse(42); const exampleSchema = z.number().positive();
  21. @gefymarcos import { z } from "zod"; Validação de numbers

    exampleSchema.parse(42); ✅ => 42 const exampleSchema = z.number().positive();
  22. @gefymarcos import { z } from "zod"; Validação de numbers

    exampleSchema.parse(42); exampleSchema.parse(-10); ✅ => 42 const exampleSchema = z.number().positive();
  23. @gefymarcos import { z } from "zod"; Validação de numbers

    exampleSchema.parse(42); exampleSchema.parse(-10); ✅ => 42 ⛔ => Input must be a positive number const exampleSchema = z.number().positive();
  24. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos
  25. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 });
  26. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: “Gefy”, age: 30 }
  27. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: “Gefy”, age: 30 }
  28. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: “Gefy”, age: 30 }
  29. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); exampleSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: “Gefy”, age: 30 }
  30. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); exampleSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: “Gefy”, age: 30 } ⛔ => Input.age should be greater than or equal to 18
  31. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string(), age: z.number().min(18) }); Validação de objetos exampleSchema.parse({ name: “Gefy”, age: 30 }); exampleSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: “Gefy”, age: 30 } ⛔ => Input.age should be greater than or equal to 18
  32. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays
  33. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays
  34. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]);
  35. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); ✅ => [1, 2, 3]
  36. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); ✅ => [1, 2, 3]
  37. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); ✅ => [1, 2, 3]
  38. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); exampleSchema.parse([-1, 2, 3]); ✅ => [1, 2, 3]
  39. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); exampleSchema.parse([-1, 2, 3]); ✅ => [1, 2, 3] ⛔ => Input[0] must be a positive number
  40. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.array(z.number().positive()); Validação de arrays exampleSchema.parse([1, 2, 3]); exampleSchema.parse([-1, 2, 3]); ✅ => [1, 2, 3] ⛔ => Input[0] must be a positive number
  41. @gefymarcos const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(),

    }) .refine( (data) => data.userType === “admin”, { Validação condicional
  42. @gefymarcos const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(),

    }) .refine( (data) = path: [“admField”] }) Validação condicional
  43. @gefymarcos const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(),

    }) .refine( (data) = path: [“admField”] }) }); Validação condicional
  44. @gefymarcos Validação condicional const exampleSchema = z.object({ userType: z.enum(["admin", “user”]),

    admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  45. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); Validação condicional const

    exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  46. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); Validação condicional ✅

    => { userType: "admin", admField: “yes" } const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  47. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); Validação condicional ✅

    => { userType: "admin", admField: “yes" } const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  48. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); Validação condicional ✅

    => { userType: "admin", admField: “yes" } const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  49. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); exampleSchema.parse({ userType: “admin”,

    admField: “no” }); Validação condicional ✅ => { userType: "admin", admField: “yes" } const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  50. @gefymarcos exampleSchema.parse({ userType: “admin”, admField: “yes" }); exampleSchema.parse({ userType: “admin”,

    admField: “no” }); Validação condicional ✅ => { userType: "admin", admField: “yes" } ⛔ => Invalid input const exampleSchema = z.object({ userType: z.enum(["admin", “user”]), admField: z.string(), }) .refine( (data) path: [“admField”] }) });
  51. @gefymarcos Composição de esquemas const userSchema = z.object({ name: nameSchema,

    age: ageSchema }); const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  52. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  53. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  54. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: "Gefy", age: 30 } const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  55. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: "Gefy", age: 30 } const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  56. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); ✅ => { name: "Gefy", age: 30 } const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  57. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: "Gefy", age: 30 } const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  58. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: "Gefy", age: 30 } ⛔ => Input.age should be greater than or equal to 18 const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  59. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: "Gefy", age: 30 } ⛔ => Input.age should be greater than or equal to 18 const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  60. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); ✅ => { name: "Gefy", age: 30 } ⛔ => Input.age should be greater than or equal to 18 const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  61. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); userSchema.parse({ name: “Gefy” }); ✅ => { name: "Gefy", age: 30 } ⛔ => Input.age should be greater than or equal to 18 const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  62. @gefymarcos const userSchema = z.object({ name: nameSchema, age: ageSchema });

    Composição de esquemas userSchema.parse({ name: “Gefy”, age: 30 }); userSchema.parse({ name: “Gefy”, age: 15 }); userSchema.parse({ name: “Gefy” }); ✅ => { name: "Gefy", age: 30 } ⛔ => Input.age should be greater than or equal to 18 ⛔ => Input must have required property 'age' const nameSchema = z.string().min(5).max(10); const ageSchema = z.number().min(18);
  63. @gefymarcos import { z } from "zod"; const exampleSchema =

    z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) }); Mensagens personalizadas
  64. @gefymarcos import { z } from "zod"; Mensagens personalizadas const

    exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  65. @gefymarcos try { exampleSchema.parse({ name: “Ge”, age: 15 }); }

    catch { } import { z } from "zod"; Mensagens personalizadas const exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  66. @gefymarcos try { exampleSchema.parse({ name: “Ge”, age: 15 }); }

    catch { } import { z } from "zod"; Mensagens personalizadas console.log(error.issues[0].message); const exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  67. @gefymarcos try { exampleSchema.parse({ name: “Ge”, age: 15 }); }

    catch { } import { z } from "zod"; Mensagens personalizadas ⛔ => Nome curto demais console.log(error.issues[0].message); const exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  68. @gefymarcos try { exampleSchema.parse({ name: “Ge”, age: 15 }); }

    catch { } import { z } from "zod"; Mensagens personalizadas ⛔ => Nome curto demais console.log(error.issues[1].message); console.log(error.issues[0].message); const exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  69. @gefymarcos try { exampleSchema.parse({ name: “Ge”, age: 15 }); }

    catch { } import { z } from "zod"; Mensagens personalizadas ⛔ => Nome curto demais ⛔ => Idade precisa ser maior que 18 console.log(error.issues[1].message); console.log(error.issues[0].message); const exampleSchema = z.object({ name: z.string().min(3, "Nome curto demais"), age: z.number().min(18, “Idade precisa ser maior que 18”) });
  70. @gefymarcos import { z } from "zod"; Validação de objetos

    aninhados const addressSchema = z.object({ street: z.string(), city: z.string() }); const exampleSchema = z.object({ name: z.string(), age: z.number(), address: addressSchema });
  71. @gefymarcos Validação de objetos aninhados import { z } from

    "zod"; const addressSchema = z.object({ street: z.string(), city: z.string() }); const exampleSchema = z.object({ name: z.string(), age: z.number(), address: addressSchema });
  72. @gefymarcos import { z } from "zod"; const userSchema =

    z.object({ username: z.string().min(6).trim().toLowerCase(), email: z.string().email(), age: z.number().positive(), }); Typescript infer ❤ type User = z.infer<typeof userSchema>;
  73. @gefymarcos import { z } from "zod"; const userSchema =

    z.object({ username: z.string().min(6).trim().toLowerCase(), email: z.string().email(), age: z.number().positive(), }); Typescript infer ❤ type User = z.infer<typeof userSchema>;
  74. @gefymarcos const userSchema = z.object({ username: z.string().min(6).trim().toLowerCase(), email: z.string().email(), age:

    z.number().positive(), }); import { z } from "zod"; Typescript infer ❤ type User = z.infer<typeof userSchema>; const validUser: User = { name: "gefymarcos", email: "[email protected]", age: 30, };
  75. @gefymarcos Validação específica const exampleSchema = z.object({ email: z.string().email(), url:

    z.string().url(), ip: z.string().ip(), positiveNumber: z.number().positive(), import { z } from "zod";
  76. @gefymarcos Validação específica const exampleSchema = z.object({ email: z.string().email(), url:

    z.string().url(), ip: z.string().ip(), positiveNumber: z.number().positive(), nonnegativeNumber: z.number().nonnegative(), import { z } from "zod";
  77. @gefymarcos Validação específica const exampleSchema = z.object({ email: z.string().email(), url:

    z.string().url(), ip: z.string().ip(), positiveNumber: z.number().positive(), nonnegativeNumber: z.number().nonnegative(), regex: z.string().regex(regex) import { z } from "zod";
  78. @gefymarcos Validação específica const exampleSchema = z.object({ email: z.string().email(), url:

    z.string().url(), ip: z.string().ip(), positiveNumber: z.number().positive(), nonnegativeNumber: z.number().nonnegative(), regex: z.string().regex(regex) }); import { z } from "zod";
  79. @gefymarcos Validações assíncronas const cepSchema = z.string().refine((cep) => validaCep(cep), {

    message: "CEP Inválido" }); cepSchema.parseAsync(“88790000"); import { z } from "zod";
  80. @gefymarcos • tRPC: APIs typesafe de ponta a ponta; •

    @anatine/zod-nestjs: Integração com o NestJS. API libraries
  81. @gefymarcos • zod-to-ts: Converter os schemas em Typescript; • zod-to-json-schema:

    Converter os schemas em JSON; • zod-to-openapi: Converter os schemas para OpenAPI; Zod-to-X
  82. @gefymarcos • ts-to-zod: Converte os tipos do TS em Zod

    Schemas; • json-schema-to-zod: Converte JSON em Zod Schemas; X-to-Zod
  83. @gefymarcos • ts-to-zod: Converte os tipos do TS em Zod

    Schemas; • json-schema-to-zod: Converte JSON em Zod Schemas; • graphql-codegen-typescript-validation-schema: Cria Zod Schemas baseados no Types do Graphql. X-to-Zod
  84. @gefymarcos • @anatine/zod-mock: Transforma os schemas em Mocks; • slonik:

    Client Postgres para Node.js usando Zod; • soly: Criar aplicações CLI com Zod. Outras
  85. @gefymarcos • Qual a importância da validação de dados; •

    O que é o Zod; • Exemplos de código validando diferentes tipos de dados; Recap
  86. @gefymarcos • Qual a importância da validação de dados; •

    O que é o Zod; • Exemplos de código validando diferentes tipos de dados; • Recursos avançados; Recap
  87. @gefymarcos • Qual a importância da validação de dados; •

    O que é o Zod; • Exemplos de código validando diferentes tipos de dados; • Recursos avançados; • Integração com Frontend e Backend; Recap
  88. @gefymarcos • Qual a importância da validação de dados; •

    O que é o Zod; • Exemplos de código validando diferentes tipos de dados; • Recursos avançados; • Integração com Frontend e Backend; • Boas práticas de validação. Recap
  89. @gefymarcos • https: / / github.com/colinhacks/zod • https: / /

    zod.dev/ • https: / / www.totaltypescript.com/tutorials/zod Links importantes