Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

483
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda