DEV Community

Kevin Le
Kevin Le

Posted on

Type-safely parsing JSON to a TypeScript Interface

Let's say we're working with a REST API that returns a JSON string representing a user. The JSON API agrees to a contract that it returns a string firstName, a string lastName and a number accountBalance. We model the user as an Interface in TypeScript as follow:

interface User {
    firstName: string;
    lastName: string;
    accountBalance: number;
}
Enter fullscreen mode Exit fullscreen mode

The following code is sufficient if we always have the happy path:

const json = '{"firstName": "Kevin", "lastName": "Le", "accountBalance": 100}'
const user: User = JSON.parse(json)
Enter fullscreen mode Exit fullscreen mode

But things can go wrong on the API side. The json string returned could be:

const json  '{"firstName": "Kevin", "lastName": "Le", "accountBalance": "100"}'
const user: User = JSON.parse(json)
console.log(user)
Enter fullscreen mode Exit fullscreen mode

The code does not blow up because accountBalance is now being treated as an any instead of a number. But this "forgiving" behavior leads to other problem downstream:

const balanceAfterInterest = user.accountBalance + user.accountBalance * 0.05
console.log(balanceAfterInterest) //1005
Enter fullscreen mode Exit fullscreen mode

The balanceAfterInterest is only supposed to be 105. A better approach is to catch this problem early and handle it immediately and appropriately.

Head over to https://app.quicktype.io.

Paste the string {"firstName": "Kevin", "lastName": "Le", "accountBalance": 100} to the left pane. Type User as the Name, and select JSON as the Source type.

Alt Text

In the box on the right, select TypeScript as the Language and make sure Verify JSON.parse results at runtime is turned-on. Quicktype will generate the resulting code with instruction on how to use it in the middle.

Alt Text

Now the following code can be much safer:

import { Convert, User } from "./user";

const json =
  '{"firstName": "Kevin", "lastName": "Le", "accountBalance": "100"}';

try {
  const user = Convert.toUser(json);
  console.log(user);
} catch (e) {
  console.log("Handle error", e);
}
Enter fullscreen mode Exit fullscreen mode

The exception is now caught and handled early:

Alt Text

The generated code by quicktype for user.js is:

Top comments (2)

Collapse
 
timo_redwit profile image
TIMO(JongHyeok Kang)

cool! I use ajv when validate type of any object

Collapse
 
insytes profile image
insytes

amour, roam, arum mora... I made these words using 5 of your function names :)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.