nope-validator icon indicating copy to clipboard operation
nope-validator copied to clipboard

Is it possible to infer the type of an object schema?

Open christopher-caldwell opened this issue 8 months ago • 3 comments

Question

I'd like to be able to get a type / interface from an object type, similar to the way Zod does it. Zod is quite heavy, and I dig the lightweight approach here. This should not impact the bundle size or performance, because it's all in TS.

Another example from Superstruct

Something like:

import Nope from 'nope-validator'

const userSchema = Nope.object().shape({
  name: Nope.string().atMost(15).required(),
  email: Nope.string().email("Please provide a valid email").required(),
  favoriteColor: Nope.string()
});

type User = Nope.infer<typeof userSchema>  // { name: string; email: string; favoriteColor?: string }

Were the docs unclear about it?

Nothing mentioned, that I could find.

christopher-caldwell avatar Dec 08 '23 20:12 christopher-caldwell

Hi @christopher-caldwell, appreciate your question!

Currently, we don't have the capability to infer object schemas like Zod or Superstruct in our tool. I understand the importance of a lightweight approach without impacting bundle size or performance. Your suggestion is valuable, and I'll make sure to add it to our feature backlog for consideration.

Once we have any updates or developments on this front, I'll be sure to share them with you.

Thanks again for your input 🚀

ftonato avatar Dec 08 '23 21:12 ftonato

@christopher-caldwell

I know this is the actual "opposite" of what you need, but I am making my schema and my form values "tighter" with a helper function to create and type the Nope Schema shape.

Here is the function:

export const createSchema = <T extends Record<string, unknown>>(
  schemaBody: { [K in keyof T]: Validatable<T[K]> }
) => {
  return Nope.object().shape(schemaBody);
};

and here is an example

const userFormValues = {
  username: '',
  password: '',
  confirmPassword: '',
};

// UserFormSchema -> NopeObject 
const UserFormSchema = createSchema<typeof userFormValues>({
  username: Nope.string().email('Must be a valid email'),
  password: Nope.string().required().atLeast(8),
  confirmPassword: Nope.string(),
});

This is just for basic functionality however, it has not been tested in multiple scenarios or anything, so use it at your own risk. (as I am also using it)

irv-armenta-g avatar May 23 '24 05:05 irv-armenta-g

@christopher-caldwell

I know this is the actual "opposite" of what you need, but I am making my schema and my form values "tighter" with a helper function to create and type the Nope Schema shape.

Here is the function:


export const createSchema = <T extends Record<string, unknown>>(

  schemaBody: { [K in keyof T]: Validatable<T[K]> }

) => {

  return Nope.object().shape(schemaBody);

};

and here is an example


const userFormValues = {

  username: '',

  password: '',

  confirmPassword: '',

};



// UserFormSchema -> NopeObject 

const UserFormSchema = createSchema<typeof userFormValues>({

  username: Nope.string().email('Must be a valid email'),

  password: Nope.string().required().atLeast(8),

  confirmPassword: Nope.string(),

});

This is just for basic functionality however, it has not been tested in multiple scenarios or anything, so use it at your own risk. (as I am also using it)

This is very interesting, thanks for sharing! Looks like it could definitely work.

My "gripe" is that you have to define both your schema and your type separately, rather than derive the type.

I ended up going with superstruct, but I appreciate you sharing!

christopher-caldwell avatar May 23 '24 13:05 christopher-caldwell