You are a developer who specializes in TypeScript.

You will use the ZOD library to convert a set of static types, interfaces and enums to their zod equivilant. First there will be instructions. Then some sample input. Then some sample output.

Instructions for the task:

  • Nested Interfaces: We will create Zod schemas for each nested interface independently and reference them within their parent schemas to maintain the named structure.
  • Optional Fields: In TypeScript, optional fields are denoted with a question mark (?). In Zod, we can use .optional() method to achieve a similar effect. This means that the field may be absent or explicitly set as undefined. For example, an optional string would be z.string().optional().
  • Unions with Literals: As per your example, we will use z.union() with z.literal() for creating unions of literal types which corresponds to TypeScript’s union of string literals.
  • Literal Type Arrays: For arrays like statusValues, we’ll create a Zod schema using z.union() with each entry in the array being a z.literal(). This way, the type is kept simple, mirroring the TypeScript type it represents.
  • Nullability: When it comes to nullability, Type | null in TypeScript is equivalent to Zod’s .nullable(). The .nullable() method allows for a value to be either of the specified type or null. This is indeed best for validation purposes as it clearly defines that the value can be null and not just undefined. For example, z.string().nullable() means the field can be a string or null.
  • Put all the exports on the same line as the type or const. export all of the things.

Sample Input

here is a sample input file of typescript types

export type DateISO = string
 
interface EnrollmentStudent {
  id: string
  student: Student
}
 
interface Institution {
  name: string
  website: string
}
 
export type Permission = 'student' | 'instructor' | 'administrator'
 
export interface Student {
  id: string
  name: string
  email: string
  phone: string
  permission: Permission
  acceptedPolicies: boolean
  institution?: Institution
}
 
export interface Course {
  id: string
  title: string
  description: string
  startDate: DateISO
  
  enrollmentStudents: EnrollmentStudent[]
  
  location: string
  department: string
  courseCode: string
  
  createdAt: DateISO
  updatedAt: DateISO
}

Sample Output

here same output, but it is not exactly 1 to 1 from the input. It was a by-hand conversion by another developer.

const moduleSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string(),
  startedAt: z.string().nullable(),
  completedAt: z.string().nullable(),
  status: zStatus,
  assignmentFeed: z.array(
    z.object({
      module: z.object({
        id: z.string(),
        name: z.string(),
      }),
      unit: z.object({
        id: z.string(),
        name: z.string(),
      }),
      assignment: z.object({
        created_at: z.string(),
        created_by: z.string(),
        created_by_role: z.string(),
        files: z.array(z.string()),
      }),
    }),
  ),
})
 
export type Module = z.infer<typeof moduleSchema>

Before answering, I want you to first ask for any extra information that helps you produce a better answer. If you got no questions, please provide the answer instead


Step 2

here are the types to convert:

 

lets put it all together. Format this as a TSX file. Don’t include any explanation or any other text. It is okay if the output is large.