The way I would suggest doing this is to pull out the wordType field as a separate schema which you would then use within the z.object. Like:
const wordTypeSchema = z.enum(["verb", "adjective", "noun"]);
type WordType = z.infer<typeof wordTypeSchema>;
export const wordAPI = z.object({
words: z.array(
z.object({
id: z.string(),
word: z.string(),
translation: z.string(),
type: wordTypeSchema
})
)
});
and then I would just use the WordType type wherever else I needed just that value.
It is, however, possible to extract the type from your nested object like so:
type WordAPI = z.infer<typeof wordAPI>;
type WordType = WordAPI['words'][number]['type'];
// ^- This will include `| null` because you used `.nullable`
// If you don't want the | null you would need to say
type WordTypeNotNull = Exclude<WordType, null>;
Again, I would recommend the first approach as it's more reusable and less susceptible to needing to be updated if the object changes shape for example.
Answer from Souperman on Stack OverflowQuestion about zod inferred types
typescript - Infer type from key of object inside an array Zod - Stack Overflow
Using "zod.infer" in a specific object will cause the vs code typescript intellisense stuck forever in "Loading..."
typescript - How to infer type from a schema generated by a generic function in zod? - Stack Overflow
Currently checking the possibility of using zod library to perform schema validation.
So far it seems very interesting, however one thing is worrying me. Apart from schema validation, I would also like to automatically infer types from the zod schemas and export those same types for other projects to use.
My worry is that the inferred types from the zod schemas are not the equivalent Typescript types but actually zod generated types.
It seems to me that we can use those zod inferred types in the same way as the Typescript type equivalents (accessing properties directly, etc).
However, could exporting these types to other projects create issues that I'm not foreseeing (static type checks not working properly for example)? Also, is it considered a good practice to export those zod inferred types? Ideally we would like to generate Typescript types from zod schemas with zod, without using other external library, is there a way to do it? In this specific scenario, where we need to have schemas and infer types from it and export those to other projects, would you recommend a different library or approach for that?
» npm install zod
I got it working by using <T> with ZodType<T> instead of <T extends ZodAnyType> with <T>. Almost works as intended, as undefined will be return beside number in the getLeafValue function.
type Leaf<T> = z.infer<ReturnType<typeof LeafSchema<z.ZodType<T>>>>
type NumberLeaf = Leaf<number>
// ^? { value: number }
const getLeafValue = <T>(leaf: Leaf<T>) => leaf.value
const test = { 'value': 123 }
const val = getLeafValue(test)
// ^? { value: number | undefined }
Wrapping the z.infer with a Required<> would fix it in this example, but would make optional value (when present) also required. So, that only half the solution...
Playground
import { z } from 'zod'
const LeafSchema = <T extends z.ZodTypeAny>(valueSchema: T) => z.object({ value: valueSchema })
const LeafRefSchema = LeafSchema(z.string())
type LeafefSchemaInterface = z.infer<typeof LeafRefSchema>