Búsqueda de sitios web

typescript - ¿Cómo iterar sobre propiedades y obtener los tipos en Zod?


Supongamos que tienes un sistema básico como este en Zod:

import { z } from 'zod'

const Post = z.object({
  title: z.string(),
})

const User = z.object({
  name: z.string(),
  email: z.string().optional(),
  posts: z.array(Post),
  loginCount: z.number().min(1)
})

¿Cómo se itera a través de las propiedades e inspeccionan las opciones en las propiedades?

Veo que hay una propiedad .shape, pero ¿cómo se hace esto:

for (const name in shape) {
  const prop = shape[name]

  if (prop.min != null) {
    console.log(`Has min ${prop.min}`)
  }
  if (prop.max != null) {
    console.log(`Has max ${prop.max}`);
  }
  if (prop.optional === true) {
    console.log(`Is optional`);
  }
  if (prop.type) {
    if (prop.type is array) {
      prop.type.forEach(item => {
        console.log(`Has array item type ${item.name}`)
      })
    } else if (prop.type is union) {
      // ... show union type names
    } else {
      // show basic type name
    }
  }
}

Necesito usar esta definición para, por ejemplo:

  • Obtener las claves de cada esquema
  • Obtén el tipo de propiedad permitido(s) para una propiedad en un esquema (para que pueda saber en qué tabla de base de datos insertar, por ejemplo)
  • Hacer documentación
  • Cosas así.

No veo ninguna documentación para cosas como esta y no quiero terminar reinventando la rueda haciendo mi propia biblioteca para manejar tipos e inspección de tipos.

Respuesta #1

Zod realmente no está hecho para ser usado así, pero dependiendo de la complejidad de tus esquemas, puedes avanzar bastante mirando el código fuente: https://github.com/colinhacks/zod/blob/master/src/types.ts

Por ejemplo, puedes ver que los distintos tipos son clases, y por ejemplo que el tipo número tiene los getters minValue y maxValue. Entonces, para obtener esos valores, puedes hacer:

if (s instanceof ZodNumber)
  console.log(s.minValue, s.maxValue)

El shape que mencionas es un getter en el tipo ZodObject, lo que significa que puedes hacer:

if (s instanceof ZodObject)
  for (const field of schema.shape)
    // look at each field

También descubrirás que los esquemas opcionales y nulos son las clases ZodOptional y ZodNullable, y que ambas tienen un método unwrap() para mirar los valores internos, lo que significa que podrías hacer algo como esto:

let required = true;

while (s instanceof ZodOptional || s instanceof ZodNullable) {
  required = false;
  s = s.unwrap();
}

Si haces refinamientos o transformaciones, estos se envolverán en la clase ZodEffects, y allí verás que hay un método innerType() para acceder al tipo interno allí.

Básicamente, solo necesitas recorrer las cosas de manera recursiva, mirar cada cosa, observar de qué tipo es y tratarla según tu necesidad.

Artículos relacionados