JSON to TypeScript: Type-Safe Interfaces
When you're working with external APIs, the first thing you need is type safety. Raw any types defeat the purpose of using TypeScript. This guide shows you how to convert JSON responses into clean, reusable TypeScript interfaces - manually and with automated tools.
Why You Need TypeScript Interfaces for JSON
Every API response is just JSON. Without types, you're flying blind:
With a proper interface, TypeScript catches these issues at compile time:
How JSON Types Map to TypeScript
| JSON Type | TypeScript Type | Notes | |
|---|---|---|---|
"string" | string | Always | |
123 | number | Integers and floats both map to number | |
true/false | boolean | ||
null | null | Usually combined: string \ | null |
[1, 2, 3] | number[] | Homogeneous arrays | |
[1, "a"] | (number \ | string)[] | Mixed arrays become union types |
{} | interface | Nested objects become separate interfaces |
Handling Nested Objects
Real API responses are rarely flat. Consider this JSON:
The correct TypeScript output creates separate interfaces for each nesting level:
Optional Fields and Nullable Values
APIs often return fields that can be null or missing entirely. You need to distinguish between:
- Optional fields (
?): the key might not exist - Nullable fields (
| null): the key exists but value can benull
When generating types from a single JSON sample, a tool can't always distinguish between optional and nullable. If you see null in the sample, it becomes | null. If a field is present in some array items but not others, it becomes optional.
Automated Generation
For large API responses with dozens of nested objects, manual conversion isn't practical. Tools like the JSON to TypeScript converter analyze your JSON structure and generate all interfaces automatically, handling:
- Nested object extraction into separate interfaces
- Array type inference (including mixed-type arrays)
- PascalCase interface naming from camelCase keys
- Duplicate structure detection and reuse
Best Practices
- Start from real API responses, not documentation. Docs can be outdated; real responses show actual field types.
- Test with multiple responses to catch optional fields. A single sample might have all fields populated.
- Use
unknowninstead ofanyfor truly dynamic fields. It forces you to narrow the type before using it.
- Consider using Zod for runtime validation alongside TypeScript types. Zod schemas give you both compile-time types and runtime validation. Try our JSON to Zod converter.
- Keep interfaces in a dedicated
types/directory so they're easy to find and update when APIs change.
Going Further
- JSON Schema: If your API provides a JSON Schema, you can generate TypeScript types from it deterministically. Our JSON Schema generator creates schemas from sample data.
- Runtime validation: TypeScript types disappear at runtime. For critical data, combine with Zod or io-ts for runtime checks.
- Code generation in CI: Tools like
quicktypecan run in CI to regenerate types when schemas change.