logo
Basic Utils
Home

Zod Transform: A Deep Dive into Data Transformation

Table of Contents

1. Introduction to zod.transform

The transform method in Zod is used to modify or reshape the output of a schema after its validation step but before it is returned to the user. This is incredibly useful when you want the input to be processed or altered before you further work with it.

Zod allows developers to define validation schemas for a wide variety of data types, but raw validation alone isn’t always enough. With transform, Zod provides a flexible way to apply additional logic to the validated values.

2. Basic Syntax of zod.transform

The syntax of the transform method is straightforward. It accepts a function that takes the parsed value (i.e., the value that passed validation) and returns a modified version of it.

const schema = z.string().transform((val) => val.toUpperCase());

In the example above, we first validate that the input is a string, and then we use the transform method to convert it to uppercase. This transformation happens after the validation has already succeeded.

3. Use Cases for zod.transform

A. Transforming Strings

One of the most common use cases is transforming strings, such as converting text to lowercase, uppercase, or trimming unnecessary whitespace.

const emailSchema = z.string().email().transform((val) => val.toLowerCase().trim());

const result = emailSchema.parse("  USER@EXAMPLE.COM  ");
console.log(result);  // "user@example.com"

This is handy for normalizing input like email addresses. The string is first validated as a proper email and then transformed by making it lowercase and trimming any surrounding spaces.

B. Handling Numbers

Numbers are another frequent candidate for transformation, where you might want to format or adjust them.

const priceSchema = z.string().transform((val) => parseFloat(val));

const price = priceSchema.parse("19.99");
console.log(price);  // 19.99 (as a number)

In this example, the input is a string representation of a number, but we transform it into a JavaScript number using parseFloat. This can be useful when accepting form data where everything is received as a string.

C. Working with Arrays

Zod also allows you to transform arrays. This is useful when you want to modify the elements inside an array or change its structure.

const numberArraySchema = z
  .array(z.string())
  .transform((val) => val.map(Number));

const numbers = numberArraySchema.parse(["1", "2", "3"]);
console.log(numbers);  // [1, 2, 3] (as an array of numbers)

Here, each string inside the array is converted to a number. Zod validates that the array contains strings, then transforms them into numbers.

D. Object Transformation

You can also transform entire objects by changing their structure or individual properties.

const userSchema = z
  .object({
    firstName: z.string(),
    lastName: z.string(),
  })
  .transform(({ firstName, lastName }) => ({
    fullName: `${firstName} ${lastName}`,
  }));

const user = userSchema.parse({ firstName: "John", lastName: "Doe" });
console.log(user);  // { fullName: "John Doe" }

In this case, we take an object with firstName and lastName and transform it into a new object that only contains a fullName property. This demonstrates how transform can restructure data entirely.

4. Advanced Use Cases

A. Asynchronous Transformations

Zod supports asynchronous transformations as well. This can be particularly useful when you need to fetch additional data or perform asynchronous operations during transformation.

const asyncSchema = z
  .string()
  .transform(async (val) => {
    // Simulate an async operation, e.g., calling an API
    const result = await fakeApiCall(val);
    return result;
  });

async function example() {
  const result = await asyncSchema.parseAsync("input");
  console.log(result);
}

example();

In this example, we simulate an asynchronous API call that modifies the string input. Remember to use parseAsync instead of parse when dealing with async transforms.

B. Chaining Multiple Transforms

You can chain multiple transform calls to apply successive transformations to the data.

const schema = z
  .string()
  .transform((val) => val.trim())
  .transform((val) => val.toLowerCase());

const result = schema.parse("  HeLLo WoRLd  ");
console.log(result);  // "hello world"

Here, the input string is first trimmed and then converted to lowercase. Each transform operates on the result of the previous one, providing a step-by-step pipeline for processing data.

5. Error Handling in zod.transform

While zod.transform is a powerful tool, you need to be mindful of how errors are handled within your transform functions. If the transformation fails, you need to handle it properly or let Zod report the error.

const schema = z.string().transform((val) => {
  if (val === "") throw new Error("Cannot transform an empty string.");
  return val.toUpperCase();
});

try {
  schema.parse("");
} catch (e) {
  console.error(e);  // "Cannot transform an empty string."
}

In this case, an empty string triggers a custom error. Zod will propagate this error, allowing you to catch and handle it accordingly.

6. Common Mistakes and How to Avoid Them

Forgeting to Use parseAsync

When working with async transforms, forgetting to use parseAsync can cause your code to break.

const asyncSchema = z.string().transform(async (val) => await someAsyncOperation(val));

// This will throw an error because the transformation is asynchronous
const result = asyncSchema.parse("input"); // Use parseAsync instead

Improperly Handling Errors

Not handling errors inside the transformation function can lead to unhandled promise rejections or incorrect data being returned.

7. Best Practices for Using zod.transform

  • Keep transformations simple: Ensure that your transformation logic is straightforward to enhance readability.
  • Handle errors gracefully: Always anticipate potential errors in your transformations and handle them appropriately.
  • Document transformations: When using complex transformations, document your logic to help other developers understand your intent.

8. Conclusion

The zod.transform method is an essential part of Zod's functionality, allowing developers to modify validated data efficiently. By following the practices and use cases outlined above, you can make the most of this powerful feature in your applications.

Sources

logo
Basic Utils

simplify and inspire technology

©2024, basicutils.com