Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

478
Vistas
How to extract a single type from a Zod union type?

I'm using Zod and have an array containing different objects using a union. After parsing it I want to iterate through each item and extract it's "real" type / cut off the other types.

When checking for specific object properties, the following code works fine:

const objectWithNumber = zod.object({ num: zod.number() });
const objectWithBoolean = zod.object({ isTruthy: zod.boolean() });
const myArray = zod.array(zod.union([objectWithNumber, objectWithBoolean]));
const parsedArray = myArray.parse([{ isTruthy: true }, { num: 3 }]);

parsedArray.forEach((item) => {
  if ("num" in item) {
    console.info('objectWithNumber:', item);
    // TS knows about it => syntax support for objectWithNumber
  } else if ("isTruthy" in item) {
    console.info('objectWithBoolean:', item);
    // TS knows about it => syntax support for objectWithBoolean
  } else {
    console.error('unknown');
  }
});

An alternative would be using discriminated unions for this

const objectWithNumber = zod.object({ type: zod.literal("objectWithNumber"), num: zod.number() });
const objectWithBoolean = zod.object({ type: zod.literal("objectWithBoolean"), isTruthy: zod.boolean() });
const myArray = zod.array(zod.discriminatedUnion("type", [ objectWithNumber, objectWithBoolean ]));
const parsedArray = myArray.parse([{ type: "objectWithBoolean", isTruthy: true }, { type: "objectWithNumber", num: 3 }]);

parsedArray.forEach(item => {
  if (item.type === "objectWithNumber") {
    console.info('objectWithNumber:', item);
    // TS knows about it => syntax support for objectWithNumber
  } else if (item.type === "objectWithBoolean") {
    console.info('objectWithBoolean:', item);
    // TS knows about it => syntax support for objectWithBoolean
  } else {
    console.error('unknown');
  }
});

but I think I misunderstood this concept because there is just more code to write ( I can always add a shared property and inspect that one ). Any help on this is much appreciated :)

Are there better ways to identify a specific schema?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

If I understood you correctly, your question boils down to "Why one should use discriminated unions instead of shared fields combined with optional fields". (zod.js just lifts this concept into runtime providing validation functionality). In your example, there is in fact no reason to use a discriminator (type property), because each object holds only a single non-optional property that is mutually exclusive between types and can be easily used to distinguish types. However, the main issue with this code is that the object names (or shapes/structures) do not communicate any intentions - that's why it's difficult to see the benefits of discriminated unions.

You can think of discriminated union as a type that describes a family of objects and provides an unified mechanism (in a form of a discriminator property) to identify them. This approach is less fragile than checking for the existence of some manually picked properties (like for instance num property). What if num for any reason becomes optional? Then your check for num existence will break. Another argument for discriminated union is to decrease the number of optional properties. Compare two following examples:

// shared and optional fields instead of discriminated union
type Vehicle = {
  name: string;
  combustionEngine?: PetrolEngine | DieselEngine;
  tankCapacity?: number;
  electricEngine?: ElectricEngine;
  batteryCapacity?: number;
}
type Vehicle = 
  | GasolineCar
  | ElectricCar

type = GasolineCar {
  kind: "gasolineCar";
  name: string;
  engine: PetrolEngine | DieselEngine;
  tankCapacity: number;
}

type ElectricCar  = {
  kind: "electricCar"
  name: string;
  engine: ElecticEngine;
  batteryCapacity: number;
}

The example with discriminated union produces much more descriptive code. You don't have to add multiple checks for optional fields - instead, just identify (as early as possible) type by discriminator and pass the object to a function/method accepting the more narrow type (GasolineCar or ElectricCar instead of Vehicle).

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda