Question
Is there a TypeScript equivalent of JavaScript's JSON.parse() for converting a JSON string into an object?
For example, given this JSON string:
const jsonText = '{"name":"Bob","error":false}';
how can it be parsed and used safely in TypeScript?
Short Answer
TypeScript uses the same JSON.parse() function as JavaScript because TypeScript compiles to JavaScript. The important extra step is handling the parsed value safely: JSON.parse() returns any, so use a type assertion only when the input is trusted, or validate external data before relying on its shape.
Concept
TypeScript is a superset of JavaScript, which means normal JavaScript APIs are available in TypeScript. Therefore, parsing JSON works exactly the same way:
const value = JSON.parse(text);
JSON.parse() converts a JSON-formatted string into JavaScript values:
- A JSON object becomes a JavaScript object.
- A JSON array becomes a JavaScript array.
- JSON strings, numbers, booleans, and
nullbecome their matching JavaScript values.
The key TypeScript detail is the return type. JSON.parse() is typed as returning any. TypeScript cannot know whether a string received from an API, a file, or browser storage really contains the properties your program expects.
For example, this compiles but can fail at runtime:
interface User {
name: string;
error: boolean;
}
const user = JSON.parse('{"unexpected":123}') as User;
console.log(user.name.toUpperCase()); // Runtime error: name is undefined
A type assertion tells the TypeScript compiler what you expect, but it does not inspect or validate the parsed data. Use assertions for known, controlled JSON. For external or untrusted data, check its structure before using it.
Mental Model
Think of JSON as a sealed delivery box containing data written in a standard format.
JSON.parse()opens the box and turns its contents into a JavaScript value.- A TypeScript interface is the delivery label that says what you expect to find inside.
- Writing
as Userdoes not inspect the box. It only tells TypeScript, “Treat this as aUser.” - Validation is the actual inspection step: you open the box and confirm it contains the expected fields with the expected types.
This distinction matters because TypeScript types disappear when your code runs. Runtime data still needs runtime checks.
Syntax and Examples
Use JSON.parse() with a valid JSON string:
const jsonText = '{"name":"Bob","error":false}';
const data = JSON.parse(jsonText);
console.log(data.name); // Bob
console.log(data.error); // false
The result is a JavaScript object. To describe the expected structure, create an interface:
interface ApiResponse {
name: string;
error: boolean;
}
const jsonText = '{"name":"Bob","error":false}';
const response = JSON.parse(jsonText) as ApiResponse;
console.log(response.name.toUpperCase()); // BOB
This assertion is appropriate when your program generated the JSON itself or another trusted part of your application guarantees the format.
For possibly invalid JSON, use try...catch:
function parseJson(text: string): unknown {
try {
return JSON.parse(text);
} catch {
return null;
}
}
const result = parseJson('{"name":"Bob"}');
console.log(result);
Returning unknown is safer than returning any: it requires you to check the value before accessing properties.
Step by Step Execution
Consider this code:
interface Profile {
name: string;
error: boolean;
}
const text = '{"name":"Bob","error":false}';
const profile = JSON.parse(text) as Profile;
console.log(profile.name);
console.log(profile.error);
Execution happens in this order:
-
TypeScript reads the
Profileinterface. It describes the shape the program expects, but it produces no JavaScript at runtime. -
textstores ordinary text. At this point, it is not an object andtext.namedoes not exist. -
JSON.parse(text)reads the JSON syntax and creates an object equivalent to:{ name: "Bob", error: false } -
as Profiletells the TypeScript type checker to treat that object as aProfile. It does not change the object. -
profile.nameevaluates to"Bob". -
profile.errorevaluates tofalse.
If the text were malformed, such as '{"name":"Bob",}', JSON.parse() would throw a SyntaxError at step 3.
Real World Use Cases
JSON parsing is common whenever an application receives stored or transmitted data as text:
- HTTP APIs: Parse JSON responses from an API when using a lower-level HTTP client or processing raw response text.
- Browser storage: Read settings saved with
localStorage.setItem(). - Configuration files: Load JSON configuration for scripts, tools, or servers.
- Webhooks and message queues: Decode JSON payloads sent by other services.
- Command-line tools: Read JSON from a file or standard input.
Example: loading saved preferences from browser storage:
interface Preferences {
theme: "light" | "dark";
showTips: boolean;
}
const saved = localStorage.getItem("preferences");
if (saved !== null) {
const preferences = JSON.parse(saved) as Preferences;
console.log(preferences.theme);
}
Because browser storage can be modified manually or contain old data, production code should validate preferences before using it.
Real Codebase Usage
In real codebases, developers usually combine parsing with error handling and validation.
Parse only at system boundaries
Keep JSON parsing near the point where text enters the application, such as an HTTP response, file reader, or storage adapter. Convert it to validated application data early.
Use a guard clause for missing input
function loadSettings(text: string | null): unknown {
if (text === null) {
return null;
}
return JSON.parse(text);
}
Catch invalid JSON
function safeJsonParse(text: string): unknown | null {
try {
return JSON.parse(text);
} catch {
return null;
}
}
Validate with a type guard
A type guard checks data at runtime and informs TypeScript about the result.
interface User {
name: string;
error: boolean;
}
function isUser(value: unknown): value is User {
if (typeof value !== "object" || value === null) {
return false;
}
const candidate = value as Record<string, unknown>;
return (
typeof candidate.name === "string" &&
typeof candidate.error === "boolean"
);
}
const raw: unknown = JSON.parse('{"name":"Bob","error":false}');
if (isUser(raw)) {
console.log(raw.name.toUpperCase());
} else {
console.error("The response does not have the expected format.");
}
For large applications, teams may use a schema-validation library to define and validate complex API payloads consistently.
Common Mistakes
Using invalid JSON syntax
JSON is similar to JavaScript object syntax but is stricter. Object keys and string values must use double quotes.
// Invalid JSON: single quotes are not valid in JSON.
const broken = "{'name': 'Bob'}";
JSON.parse(broken); // Throws SyntaxError
Use valid JSON:
const valid = '{"name":"Bob"}';
JSON.parse(valid);
Forgetting that JSON.parse() can throw
Malformed input stops execution unless it is caught.
const data = JSON.parse(userProvidedText); // Can throw SyntaxError
Use try...catch when input may be invalid.
Assuming as SomeType validates data
interface User {
name: string;
}
const user = JSON.parse('{"id":42}') as User;
console.log(user.name.length); // Runtime error
A type assertion only affects compile-time checking. Validate external input with a type guard or schema.
Treating all parsed values as objects
JSON can contain any JSON value:
JSON.parse('42'); // number
JSON.parse('true'); // boolean
JSON.parse('[1, 2, 3]'); // array
JSON.parse('null'); // null
Check the kind of value you received before accessing object properties.
Parsing an object that is already parsed
const user = { name: "Bob" };
JSON.parse(user); // Type error: JSON.parse expects a string
Only parse strings. Use JSON.stringify() when you need to convert an object into JSON text.
Comparisons
| Tool or technique | Purpose | Important detail |
|---|---|---|
JSON.parse(text) | Converts JSON text to a JavaScript value | Throws when text is invalid JSON |
JSON.stringify(value) | Converts a JavaScript value to JSON text | Omits some unsupported values, such as functions |
as User | Tells TypeScript to treat a value as User | Does not validate runtime data |
| Type guard | Checks a value at runtime and narrows its TypeScript type | Useful after parsing external JSON |
unknown | Represents a value whose type is not yet known | Must be checked before use |
any | Disables most type checking for a value | Convenient but less safe; JSON.parse() returns this |
A useful workflow is:
const raw: unknown = JSON.parse(text);
if (isUser(raw)) {
// raw is a User here.
}
This is safer than immediately asserting JSON.parse(text) as User when the JSON comes from outside your control.
Cheat Sheet
// Parse JSON text
const value = JSON.parse('{"name":"Bob"}');
// Describe expected data
interface User {
name: string;
error: boolean;
}
// Trusted input only: assertion, not validation
const user = JSON.parse(text) as User;
// Handle malformed JSON
function safeJsonParse(text: string): unknown | null {
try {
return JSON.parse(text);
} catch {
return null;
}
}
// Basic runtime object check
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
Rules to remember:
- TypeScript uses JavaScript's
JSON.parse(). - JSON requires double quotes around keys and string values.
JSON.parse()throwsSyntaxErrorfor malformed JSON.- Parsed JSON may be an object, array, primitive, or
null. as Typedoes not verify the data.- Prefer validation for API responses, files, storage, and user input.
FAQ
Does TypeScript have its own JSON parser?
No. TypeScript uses JavaScript's built-in JSON.parse() because TypeScript compiles to JavaScript.
What type does JSON.parse() return in TypeScript?
It returns any. Assigning the result to unknown is often safer when the input is external.
Can I use JSON.parse<MyType>(text) with a generic type?
No. JSON.parse() does not validate or create a value from a generic type. Parse first, then validate or, for trusted data, use an assertion.
Why does JSON.parse() throw an error?
It throws a SyntaxError when the string is not valid JSON, such as when it has trailing commas or uses single quotes.
Is as User safe after parsing JSON?
Only if you fully trust the source and know it always follows the expected format. Otherwise, validate the parsed value first.
Can JSON contain dates?
JSON has no native date type. Dates are normally stored as strings and converted with new Date(value) after validating the string.
How do I parse JSON from localStorage safely?
Check whether getItem() returned null, catch parse errors, and validate the parsed value before using it.
Mini Project
Description
Build a small parser for saved user preferences. The parser receives JSON text, handles malformed input, and accepts the data only when it matches the expected preference structure. This mirrors how applications safely load browser storage or configuration files.
Goal
Create a function that returns validated preferences or falls back to default preferences.
Requirements
- Define a
Preferencesinterface withthemeandshowTipsproperties. - Define default preferences to use when input is missing or invalid.
- Parse a JSON string without allowing malformed JSON to crash the program.
- Validate that
themeis either"light"or"dark". - Validate that
showTipsis a boolean. - Return the default preferences when validation fails.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.