What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
TypeScript does not check values at runtime. Data from an API, request body, queue, database, or browser message can contradict the type your code expects, and a cast such as payload as User does not verify it. Put a runtime validation step at each boundary where untrusted data enters logic that relies on its shape, then handle business rules and security controls separately.
Why TypeScript types do not prevent production failures
TypeScript checks your code during development and compilation; its types do not inspect values as a program runs. The TypeScript Handbook explains that “A type assertion is like a type cast in other languages, but it performs no special checking or restructuring of data.” It has no runtime impact: TypeScript Handbook: Type Assertions.
As an Amazon Associate I earn from qualifying purchases.
For example, const user = payload as User tells the compiler to trust that payload is a User. It does not check that id or email exists, that age is a number, or that the payload is even an object. If the assumption is false, code that reads or uses those values can fail later—or make a bad decision without throwing an error.
Represent data you have not checked as unknown. Unlike any, unknown requires you to establish what the value is before using it as a specific application type.
#1 Best Overall
Where to put runtime validation
Validate data when it crosses into a component whose logic depends on the data meeting a contract. OWASP recommends validating untrusted inputs early, including data from network-facing clients and internal feeds. A source being inside your organization does not guarantee that its data is current or well-formed: OWASP Input Validation Cheat Sheet and OWASP JavaScript and TypeScript Cheat Sheet.
- Incoming HTTP requests: Validate on the server even if a browser also validates the form. Clients can be changed, bypassed, or out of date.
- Third-party API responses: Check the response before application code assumes fields, types, or allowed values.
- Queues and partner feeds: Validate messages at the consuming component’s boundary. Producers and consumers may deploy independently, and old or malformed records can persist.
- Stored data: Validate when a component reads data whose shape it relies on. Database or storage contents can outlive the code version that created them.
- Browser messages and other integrations: Treat received values as untrusted until checked against the receiving code’s contract.
Validation at one boundary does not automatically cover every later boundary. For example, a request can be checked when accepted and still need validation when read by a separate worker from a queue.
Validate an API response with Zod
A Zod schema can perform the runtime check and provide the corresponding TypeScript type. The example below treats the parsed response as unknown, catches both JSON decoding failures and schema failures, and returns only a validated value:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
import * as z from "zod";
const UserSchema = z.object({
id: z.string(),
email: z.email(),
age: z.number().int().nonnegative(),
});
type User = z.infer<typeof UserSchema>;
async function loadUser(response: Response): Promise<User> {
let input: unknown;
try {
input = await response.json();
} catch {
throw new Error("Response body is not valid JSON");
}
return UserSchema.parse(input);
}
z.infer derives the TypeScript type from the schema, so the runtime contract and static type share a definition. .parse() returns validated data or throws a ZodError if the value fails the schema. In real application code, decide how the caller should handle a decoding or validation failure rather than letting an unhandled exception determine the outcome. See Zod: Basic usage.
The example validates the response body’s JSON shape; it does not establish that the HTTP request succeeded. Check the response status and any relevant response metadata separately before treating its body as the expected resource.
Choose between .parse() and .safeParse()
Both methods validate against the schema. Choose based on how you want invalid input to flow through the code:
| Method | Invalid input | Use it when |
|---|---|---|
.parse(input) |
Throws a ZodError. |
Exceptions fit the surrounding error-handling path and invalid data should abort the operation. |
.safeParse(input) |
Returns a discriminated result with success: false and an error. |
You want an explicit branch for expected invalid input, such as returning a client error or discarding a malformed message. |
With .safeParse(), use the success check to narrow the result before accessing its data:
const result = UserSchema.safeParse(input);
if (!result.success) {
// Map the validation error to an appropriate response or handling path.
return;
}
const user = result.data;
For a schema with asynchronous refinements or transforms, use .parseAsync() or .safeParseAsync() rather than the synchronous methods. The method choice changes failure control flow, not the need to handle the failure.
Check meaning, not just data shape
A value can have the expected primitive type and still be invalid for the operation. A number may be outside an allowed range; two valid dates may be in the wrong order; a string may name an unsupported status. Define structural requirements in the schema and add checks for relationships and rules that give the data business meaning. OWASP’s Business Logic Security Cheat Sheet covers risks arising from invalid business assumptions.
- Require fields and constrain their types, formats, and allowed choices.
- Set meaningful numeric ranges and string or array length limits.
- Check relationships between fields, such as a start date preceding an end date.
- Keep operation-specific rules—such as whether a user may perform an action—in the appropriate business and authorization logic.
Coercion is not validation by itself. For example, z.coerce.number() uses JavaScript number conversion. That may be right for a contract that accepts numeric text, but conversion can produce values that still violate the intended rules. Follow coercion with constraints that express what the operation accepts. See Zod: API.
Decide what to do with unknown object keys
Object-key policy is part of the contract between a producer and a consumer. Zod object schemas strip unrecognized keys by default; strict objects reject them, while loose objects preserve them. Choose according to what the receiving component is meant to accept, rather than treating one policy as universally correct. The Zod API documentation describes these object behaviors.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Strip: Accept recognized fields and omit unrecognized ones from the parsed result.
- Reject: Fail validation when extra keys appear. This can expose unexpected input or contract drift.
- Preserve: Keep extra keys when the receiving contract intentionally allows them.
For nested objects and arrays, define the expected structure recursively. Apply limits to field lengths and array sizes where appropriate; checking item types alone does not bound the amount of work or data the application must handle.
Best Value
What Zod validation does not protect
Validation is one control, not a complete security boundary. A well-formed value is not automatically authorized, safe to render, or safe to place into a command or query. OWASP’s Input Validation Cheat Sheet recommends using defenses suited to the destination and operation.
- Limit resources before parsing: Schema validation runs after a parser has produced a value. Enforce request-body size and parser-depth limits in the framework or transport before buffering and parsing, where supported.
- Authorize separately: A valid user ID or action value does not prove the caller is permitted to access the associated resource.
- Use parameterized database queries: A string that passes schema checks is not safe to interpolate into SQL.
- Encode output for its context: Valid input is not automatically safe HTML, JavaScript, or other rendered output.
- Handle rich content, files, paths, and redirects with destination-specific controls: A schema cannot replace safe file handling, path checks, or redirect policy.
- Limit error exposure and logging: Return feedback appropriate to the client, and avoid logging full request bodies that may contain secrets or personal data.
Check Zod and TypeScript compatibility
Zod’s official documentation currently describes Zod 4 as stable and identifies zod/v4 as its flagship package. It states that Zod is tested against TypeScript 5.5 and later and requires TypeScript’s strict mode: Zod 4. These compatibility details and APIs can change, so check the documentation for the version installed in your project.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems




