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

Custom schema example for template literals gives type error #2074

Closed
becpeck opened this issue Feb 21, 2023 · 4 comments
Closed

Custom schema example for template literals gives type error #2074

becpeck opened this issue Feb 21, 2023 · 4 comments
Labels
documentation Improvements or additions to documentation

Comments

@becpeck
Copy link

becpeck commented Feb 21, 2023

In the Custom schemas section of the docs, this example is given for creating a template literal schema:

const px = z.custom<`${number}px`>((val) => /^\d+px$/.test(val));
px.parse("100px"); // pass
px.parse("100vw"); // fail

As is, this example shows an error on val being passed into test:

Argument of type 'unknown' is not assignable to parameter of type 'string'.

z.custom() takes parameter check?: ((data: unknown) => any) | undefined, while test.() takes parameter string: string.

I think ideally, there should be a way to annotate or infer the type of data, but that section is pretty empty.
I found two ways around the type error, one of which would be good to update the docs with:

const pxWithAs = z.custom<`${number}px`>((val) => /^\d+px$/.test(val as string));
const pxWithTemplate = z.custom<`${number}px`>((val) => /^\d+px$/.test(`${val}`));

Playground link showing the error and ways around

I don't like either of these that much, and I'll probably be using z.templateLiteral() after #1786 is merged, but the docs example should be updated with whatever method is recommended to avoid the error.

@JacobWeisenburger
Copy link
Contributor

Is this what you are looking for?

const px = z.custom<`${ number }px`>( x => /^\d+px$/.test( z.string().parse( x ) ) )
console.log( px.safeParse( '100px' ).success ) // true
console.log( px.safeParse( '100vw' ).success ) // false

If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏
https://github.com/sponsors/JacobWeisenburger

@JacobWeisenburger JacobWeisenburger added the documentation Improvements or additions to documentation label Feb 21, 2023
@JacobWeisenburger
Copy link
Contributor

Fixed here: 1749657

This is still not a great example of z.custom, because you could easily use z.string().regex(), but I can't think of any good example that can't be solved with an already existing zod schema.

@matthewoates
Copy link

matthewoates commented Mar 9, 2023

@JacobWeisenburger how about a more strict string validator that makes sure the first letter is capitalized? That makes sense for my CMS. I tried the following but I don't see how I can plug it back into the other validation rules - z.custom<string>(Capitalize).min(3).max(50)

My likely incorrect attempt:

const zCapitalized = (val: unknown) => {
  if (!(typeof val === 'string')) return false;
  const c = val[0];
  return c && c === c.toUpperCase();
};

export const NodeWithoutTimestampsSchema = z.object({
  // id: NodeIDSchema,
  WIP: z.boolean().optional(),
  slug: z
    .string()
    .min(3)
    .max(50)
    .regex(/^[a-z0-9\-]+$/),
  // this z.custom<string> probably should be part of the zCapitalized value
  title: z.custom<string>(zCapitalized), // I want to chain .min(3).max(50),
  seoDescription: z.string().min(3).max(200),
  createdAt: z.string().min(1).optional(),
  updatedAt: z.string().min(1).optional()
});

@matthewoates
Copy link

matthewoates commented Mar 9, 2023

Oh, it looks like refine is actually what I want here. Does anyone else find that confusing?

And once again with refine, I don't see how to chain multiple refines. Just how to slap it around the entire validation rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants