typescript
json
mocks

Generate data from interfaces in TypeScript.

November 24, 2022
4 min of reading
interface User {
  id: ExtraTypes.ID;
  nickname: ExtraTypes.FULL_NAME;
  avatar: ExtraTypes.AVATAR;
  level: ExtraTypes.AGE;
  premium: boolean;
  phoneNumber: ExtraTypes.PHONENUMBER;
  game: Game
}

interface Game {
  gameId: ExtraTypes.ID;
  title: string;
  kills: number;
  deaths: number;
}

Some time ago, while working on a project, I was adding all the types that came from an API response to improve the UI development experience. Luckily, someone told me about a Visual Studio Code plugin that automatically generates TypeScript types from the backend response. It was a huge help. If you haven't tried this tool yet, check it out here: Thunder Client.

But you can easily face the reverse situation: the backend API might not be finished yet, or the data you need on the client side might be generated later. That’s where I started looking for a solution that could do the opposite—generate development‑purpose data from TypeScript interfaces. (Yes, there are similar data generators for the backend, depending on what you’re using.) Since I was working strictly on the frontend, I set out to find something that would help. I couldn’t find anything tailored to my problem, so I fell back on another great tool—Faker—which generates all sorts of data (phone numbers, usernames, avatars, images… highly recommended).

This led me to repeat the process in many parts of the application, so I asked myself: How hard could it be to build this? I spent a few hours on a proof of concept. I didn’t want to invest too much time, and my initial goal was simply: given an interface, return a JSON object. First, I would handle primitive types like boolean, string, number, Date, and undefined; if that worked, I’d push it further. I started with an interface like this:

interface User {
  id: string;
  nickname: string;
  avatar: string;
  level: number;
  premium: boolean;
}

If everything went as planned, the result should be an object shaped like this, with somewhat realistic data:

{
  "id": "051191f5-adba-437b-8061-45ab1a6194eb",
  "nickname": "Mrs. Matthew Jacobi",
  "avatar": "https://cloudflare-ipfs.com/ipfs/Qm/avatar/732.jpg",
  "level": 90,
  "premium": true
}

What started as a "few‑hour task" took a few days, but here’s the outcome of the project.

Things to keep in mind: This version supports nested interfaces—yes—but with some restrictions. For example, this will work fine:

interface ChatMessage {
  created_at: number;
  message: Message;
  publisher: string;
  channel?: string;
  timestamp: string;
}

interface Message {
  text: string;
  reply: boolean;
  forward?: string;
  groupInvite?: string;
  message?: { text: string };
  file: { name: string; id: string };
}

But this won’t (yet):

interface ChatMessage {
  created_at: number;
  messages: Array<Message>; // <<<< esto fallará por ahora... use esto mejor Message[]
  publisher: string;
  channel?: string;
  timestamp: string;
}

interface Message {
  text: string;
  reply: boolean;
  forward?: string;
  groupInvite?: string;
  message?: { text: string };
  file: { name: string; id: string };
}

I’ve also added other types that are handy for generating more realistic data you can access them simply with ExtraTypes. and you’ll see several properties for your mocks.

Finally, you can generate an array with lots of data using nothing more than your TypeScript interfaces.

Thanks for reading; I hope this is useful to whoever needs it :D. carlosmanotas.com

Carlos Manotas - Blog - from-interfaces-to-json