Challenge 1: Type process.env — Possible Solution ==================================================================== import { z } from "zod"; const ConfigSchema = z.object({ NODE_ENV: z.enum(["development", "production", "test"]), PORT: z.coerce.number().int().positive(), LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]), }); type Config = z.infer; // Example: given these environment variables — // NODE_ENV=production // PORT=8080 // LOG_LEVEL=warn // ConfigSchema.parse(process.env) returns: // { NODE_ENV: "production", PORT: 8080, LOG_LEVEL: "warn" } // Note PORT is the *number* 8080, not the string "8080". // A quick manual check without needing real env vars: const parsed = ConfigSchema.parse({ NODE_ENV: "production", PORT: "8080", // strings are exactly what process.env actually gives you LOG_LEVEL: "warn", }); console.log(typeof parsed.PORT); // "number" console.log(parsed.LOG_LEVEL); // "warn" // Passing an invalid LOG_LEVEL throws immediately: // ConfigSchema.parse({ NODE_ENV: "production", PORT: "8080", LOG_LEVEL: "verbose" }); // -> ZodError: Invalid enum value. Expected 'debug' | 'info' | 'warn' | 'error', received 'verbose' WHY THIS WORKS -------------- - z.coerce.number() converts the string "8080" into the number 8080 as part of validation — no separate parseInt() call needed, and it still rejects genuinely non-numeric strings like "abc". - z.enum([...]) restricts LOG_LEVEL to exactly the four allowed literal strings — a typo like "wran" fails validation instead of silently being accepted as a string. - `type Config = z.infer` means Config always matches the schema exactly — there's no second, hand-written interface that could drift out of sync with what's actually validated.