Skip to Content

typia.json.*Parse โ€” JSON.parse with built-in validation

Native JSON.parse(text) happily returns any. Thereโ€™s no way to be sure the parsed object matches the type you expect. typia closes that gap by combining JSON.parse with one of the validators in a single call.

signatures
namespace json { function isParse<T>(input: string): Primitive<T> | null; // is + JSON.parse function assertParse<T>(input: string): Primitive<T>; // assert + JSON.parse function validateParse<T>(input: string): IValidation<Primitive<T>>; // validate + JSON.parse }

Each function maps to one of the runtime validators, but validation starts only after native JSON.parse succeeds:

FunctionValid JSON matching TValid JSON not matching TMalformed JSON
json.isParse<T>returns the parsed valuereturns nullthrows SyntaxError
json.assertParse<T>returns the parsed valuethrows TypeGuardErrorthrows SyntaxError
json.validateParse<T>returns IValidation.ISuccess<T>returns IValidation.IFailurethrows SyntaxError

The factory functions createIsParse, createAssertParse, and createValidateParse produce parsers with the same outcomes.

First example

hello-assertParse.ts
import typia, { tags } from "typia"; interface User { id: string & tags.Format<"uuid">; name: string; } const text: string = await fetch("/me").then((r) => r.text()); const user = typia.json.assertParse<User>(text); // โ†’ parsed User when text is valid JSON matching User. // Throws SyntaxError for malformed JSON or TypeGuardError for a type mismatch.
examples/src/json/assertParse.ts
import typia, { tags } from "typia"; const json: string = JSON.stringify(typia.random<IMember>()); const parsed: IMember = typia.json.assertParse<IMember>(json); console.log(json === JSON.stringify(parsed)); // true interface IMember { id: string & tags.Format<"uuid">; email: string & tags.Format<"email">; age: number & tags.Type<"uint32"> & tags.ExclusiveMinimum<19> & tags.Maximum<100>; }

Return type

JSON canโ€™t represent everything TypeScript can. Primitive<T> is the projection of T into the โ€œwhat survives a JSON round-tripโ€ world:

In TIn Primitive<T>
methods (functions)removed
Datestring & tags.Format<"date-time"> (because JSON.stringify(date) returns an ISO string)
Set<U>, Map<K,V>, Uint8Array, โ€ฆ other native classesnever (i.e. youโ€™ll get a compile error on use)
bigintnever
class Foo { โ€ฆ }the plain object form

The error from Primitive<T> collapsing to never is the type system telling you: this field cannot survive JSON parsing. Choose a JSON-representable type, or use typia.protobuf for binary data, or typia.plain.clone when you donโ€™t actually need JSON.

For example:

import typia, { Primitive } from "typia"; interface Original { id: string; joinedAt: Date; tags: Set<string>; } // Primitive<Original> is, conceptually: // { // id: string; // joinedAt: string & tags.Format<"date-time">; // tags: never; // โ†’ compile error if you call assertParse<Original> here // }
export namespace json { export function isParse<T>(input: string): Primitive<T> | null; export function assertParse<T>(input: string): Primitive<T>; export function validateParse<T>(input: string): IValidation<Primitive<T>>; }

Reusable factories

If you parse the same T from many places, hoist the parser once:

const parseUser = typia.json.createAssertParse<User>(); const tryParseUser = typia.json.createIsParse<User>(); const validateParseUser = typia.json.createValidateParse<User>();
examples/src/json/createIsParse.ts
import typia, { tags } from "typia"; export const parseMember = typia.json.createIsParse<IMember>(); interface IMember { id: string & tags.Format<"uuid">; email: string & tags.Format<"email">; age: number & tags.Type<"uint32"> & tags.ExclusiveMinimum<19> & tags.Maximum<100>; }

Where to go next

Last updated on