Búsqueda de sitios web

typescript - Añadir método de extensión fluida a la clase de terceros


Estoy usando zod que permite definir algunas reglas de validación usando funciones encadenadas.

Especialmente, una de las funciones es opcional, que permite declarar un campo como opcional. Desafortunadamente, esta función no acepta una bandera para activar/desactivar el comportamiento opcional. En mi caso, el formulario se construye de manera dinámica y la bandera opcional debe definirse en tiempo de ejecución.

Puedo crear un pequeño método utilitario para agregar esta lógica :

import { z, ZodType} from 'zod';

const fieldIsRequired = true;

// Method 1 : wrapper / Working
const makeOptional = (input : ZodType, required : boolean): ZodType => required ? input : input.optional();

const entry1 = makeOptional(
    z
    .string()
    .min(10)
    .max(100)
    , !fieldIsRequired
);

Esto está funcionando bien, pero perdí el código fluent. Tener una regla es aceptable, pero agregar más reglas conducirá a una hamburguesa de llamadas de función y parámetros

¿Cómo puedo agregar una nueva función fluida al tipo zod, que proviene de una biblioteca de terceros?

He intentado implementar métodos de extensión, pero no pude encontrar la sintaxis correcta.

Esto es lo que intenté:

import { z, ZodType} from 'zod';

const fieldIsRequired = true;

// Method 2 : extension method / Not Working

declare namespace zod {
    export abstract class ZodType {
        makeOptional: (required: boolean)=> ZodType;
    }
}
// Add syntaxic sugar to the Zod schema
ZodType.prototype.makeOptional = function (required: boolean): ZodType {
    return required ? this : this.optional();
};

const entry2 =   
  z
    .string()
    .min(10)
    .max(100)
    .makeOptional(!fieldIsRequired);

¿Cómo solucionar esto?

Repro : TS playground

Respuesta #1

Estuviste muy cerca. Creo que necesitabas declare module y no declare namespace. Esto me funciona:

import { z, ZodType } from 'zod';

const fieldIsRequired = true;

declare module 'zod' {
    export interface ZodType {
        makeOptional: (required: boolean)=> ZodType;
    }
}
// Add syntaxic sugar to the Zod schema
z.ZodType.prototype.makeOptional = function (required: boolean): ZodType {
    return required ? this : this.optional();
};

const entry2 =   
  z
    .string()
    .min(10)
    .max(100)
    .makeOptional(!fieldIsRequired);

Parque infantil

Notas

Descubrí esto mirando la sección de Ampliación de Módulos de la documentación de TypeScript. Casi hice una publicación diciendo que no era posible ya que la siguiente sección dice algo sobre la fusión de clases, pero luego noté que estaban usando declare module.

Artículos relacionados