JSON Processing in TypeScript: Typing, Parsing, and Data Validation

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

JSON Processing in TypeScript: From Basic Parsing to Strict Typing



TypeScript, as a superset of JavaScript, inherits all built-in methods for working with JSON but adds a powerful type system. However, the standard JSON.parse() returns the any type, which negates all the benefits of static typing. In this article, we will explore how to safely and efficiently process JSON in TypeScript, using both native capabilities and specialized libraries.



The Problem with Standard JSON.parse



Consider a typical scenario:



const jsonString = '{"name":"Alice","age":30}';const user: any = JSON.parse(jsonString); // type anyconsole.log(user.name.toUpperCase()); // Runtime error if name is missing


TypeScript will not warn you if the JSON structure does not match expectations. The solution is to use type assertion or, better yet, runtime validation.



Basic Type Assertion



The simplest way is to explicitly specify the result type:



interface User {  id: number;  name: string;  email?: string;}

const raw = '{"id":1,"name":"Bob"}';const user = JSON.parse(raw) as User;console.log(user.name); // TypeScript knows this is a string


Drawback: if the JSON arrives with different fields, an error will only occur at runtime. This is unsafe when working with external APIs.



Recursive and Conditional Types for JSON



TypeScript allows you to describe any JSON using a recursive type:



type JSONValue =   | string  | number  | boolean  | null  | JSONValue[]  | { [key: string]: JSONValue };

function safeParse(json: string): JSONValue | Error { try { return JSON.parse(json) as JSONValue; } catch (e) { return new Error('Invalid JSON'); }}


This approach guarantees that the result will always be a valid JSON structure, but it does not check the specific shape.



Zod Library — Runtime Schema Validation



Zod is the most popular library for declarative data validation in TypeScript. It allows you to describe a schema and automatically derive a type from it.



Installation

npm install zod


Usage Example



import { z } from 'zod';

// Describe the schemaconst UserSchema = z.object({ id: z.number().positive(), name: z.string().min(1), email: z.string().email().optional(), role: z.enum(['admin', 'user']).default('user'),});

// Infer the type from the schematype User = z.infer<typeof UserSchema>;

// Safe parsingconst result = UserSchema.safeParse(JSON.parse(rawJson));

if (result.success) { // result.data has type User console.log(result.data.name);} else { console.error(result.error.format());}


Zod automatically checks types, field requiredness, default values, and returns detailed errors. It is an ideal choice for processing data from REST APIs or configuration files.



io-ts Library — Functional Approach



io-ts is based on functional programming and the fp-ts library. It uses codec composition for decoding/encoding data.



Example



import * as t from 'io-ts';import { isRight } from 'fp-ts/lib/Either';

const UserCodec = t.type({ id: t.number, name: t.string, tags: t.array(t.string),});

const decoded = UserCodec.decode(JSON.parse(raw));

if (isRight(decoded)) { // decoded.right — typed object console.log(decoded.right.name);} else { // decoded.left — validation errors console.log(decoded.left);}


io-ts is more strict and mathematically correct but requires an understanding of functional concepts (Either, pipe).

Recommendations