Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to define and reuse schemas for primative types #269

Open
elee1766 opened this issue Sep 18, 2024 · 6 comments
Open

Ability to define and reuse schemas for primative types #269

elee1766 opened this issue Sep 18, 2024 · 6 comments
Labels
question Further information is requested workaround available

Comments

@elee1766
Copy link

elee1766 commented Sep 18, 2024

Feature description

I would like to define a schema for an existing type somehow, and use that instead of defining a format everywhere.

For instance, it would be nice to be able to do something like

/**
 *  0x prefixed hexadecimal string
 *
 *  @pattern ^0x[a-fA-F0-9]*$
 */
export type Hex = `0x${string}`

export interface Foo {
   lorum: Hex
}
export interface Bar {
   ipsum: Hex
}

which would ideally output something like

export const hexSchema = z.string().regex(/^0x[a-fA-F0-9]*$/)
export const fooSchema = z.object({lorum: hexSchema})
export const barSchema = z.object({ipsum: hexSchema})

This could potentially also allow schema from third party package to be supported (though their definitions may have to be declared using something other than the jsdoc)

I have not looked too deeply into the code - does something like this seem feasible to implement?

@tvillaren
Copy link
Collaborator

Hello @elee1766

I'm not sure what you're asking 😄

👉 ts-to-zod does not support the template literal 0x${string} but the following input:

/**
 *  0x prefixed hexadecimal string
 *
 *  @pattern ^0x[a-fA-F0-9]*$
 */
export type Hex = string;

export interface Foo {
  lorum: Hex;
}
export interface Bar {
  ipsum: Hex;
}

will output:

// Generated by ts-to-zod
import { z } from "zod";

export const hexSchema = z.string().regex(/^0x[a-fA-F0-9]*$/);

export const fooSchema = z.object({
  lorum: hexSchema,
});

export const barSchema = z.object({
  ipsum: hexSchema,
});

👉 it also supports imports, so if you you want to have

/**
 *  @pattern ^0x[a-fA-F0-9]*$
 */
export type Hex = string;

in a specific file — say hexa.ts — and the corresponding generated zod validator in hexa.zod.ts then, if you them in your ts-to-zod.config.js like that:

/**
 * ts-to-zod configuration.
 *
 * @type {import("./src/config").TsToZodConfig}
 */
module.exports = [
  { name: "hexa", input: "src/hexa.ts", output: "src/hexa.zod.ts" },
];

any file importing Hex from hexa.ts will automatically import the validator in its generated zod file:

// Input

import { Hex } from "./hexa";
export interface Foo {
  lorum: Hex;
}

// Output

import { z } from "zod";
import { hexSchema } from "./hexa.zod";

export const fooSchema = z.object({
  lore: hexSchema
});

👉 As for 3rd party libraries, if you have a specific example, we could evolve the Config specification to enable imports of Zod Schema from those.

@elee1766
Copy link
Author

oh, maybe it was the templated literal that was messing with things then? It wasn't working for me. Let me try again and see what happens.

thanks!

@tvillaren
Copy link
Collaborator

Hey @elee1766,
Have you had a chance to try it again?

@tvillaren tvillaren added the question Further information is requested label Oct 7, 2024
@elee1766
Copy link
Author

elee1766 commented Oct 7, 2024

hey yeah!

so it's working for us for string types but not string template types.

it would be nice if we could also get it working for a string template type. is there any way we can hack around it ?

@tvillaren
Copy link
Collaborator

Hey,
I don't think it is very easy to handle this kind of string template with JSDoc tag, there would be too many specific cases to handle IMO.

A workaround you can rely on is the use of the @schema tag:

// input
/**
 *  0x prefixed hexadecimal string
 *
 *  @schema string().regex(/^0x[a-fA-F0-9]*$/)
 */
export type Hex = `0x${string}`;

// output
// Generated by ts-to-zod
import { z } from "zod";

export const hexSchema = z.string().regex(/^0x[a-fA-F0-9]*$/);

You basically can define whatever you want to be output after the z for your schema that way.

@elee1766
Copy link
Author

that is good enough i think!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested workaround available
Projects
None yet
Development

No branches or pull requests

2 participants