DEV Community

Cover image for Generating Typescript interfaces from JSON on VS Code
Firmino Changani
Firmino Changani

Posted on

Generating Typescript interfaces from JSON on VS Code

If you caught yourself setting variables using the any type from typescript to declare variables that will hold the response object coming from an HTTP operation, then this article may help you to tackle that in the future.

Table of contents

The problem that's not exactly a problem

Let's suppose you're building a web application that has the requirement of fetching the information regarding all the repositories of a specific user on Github. Knowing Github large payload, you might try to define a constant like this:



// ...
const response = await fetch(`https://api.github.com/users/${user}/repos`);
const userRepositories: any = await response;
// ...


Enter fullscreen mode Exit fullscreen mode

Whilst this is a valid approach, you'd lose Typescript's type safety and predictability since userRepositories type was set to any.

One quick way to tackle this is by defining an interface beforehand. However here comes the problem: who likes to manually define the interface our interfaces of a response payload as large as this:



{
  "id": 178168699,
  "node_id": "MDEwOlJlcG9zaXRvcnkxNzgxNjg2OTk=",
  "name": "all-contributors",
  "full_name": "flowck/all-contributors",
  "private": false,
  "owner": {
      "login": "flowck",
      "id": 1679333,
      "node_id": "MDQ6VXNlcjE2NzkzMzM=",
      "avatar_url": "https://avatars1.githubusercontent.com/u/1679333?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/flowck",
      "html_url": "https://github.com/flowck",
      "followers_url": "https://api.github.com/users/flowck/followers",
      "following_url": "https://api.github.com/users/flowck/following{/other_user}",
      "gists_url": "https://api.github.com/users/flowck/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/flowck/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/flowck/subscriptions",
      "organizations_url": "https://api.github.com/users/flowck/orgs",
      "repos_url": "https://api.github.com/users/flowck/repos",
      "events_url": "https://api.github.com/users/flowck/events{/privacy}",
      "received_events_url": "https://api.github.com/users/flowck/received_events",
      "type": "User",
      "site_admin": false
  },
  "html_url": "https://github.com/flowck/all-contributors",
  "description": "✨ Recognize all contributors, not just the ones who push code ✨",
  "fork": true,
  "url": "https://api.github.com/repos/flowck/all-contributors",
  "forks_url": "https://api.github.com/repos/flowck/all-contributors/forks",
  "keys_url": "https://api.github.com/repos/flowck/all-contributors/keys{/key_id}",
  "collaborators_url": "https://api.github.com/repos/flowck/all-contributors/collaborators{/collaborator}",
  "teams_url": "https://api.github.com/repos/flowck/all-contributors/teams",
  "hooks_url": "https://api.github.com/repos/flowck/all-contributors/hooks",
  "issue_events_url": "https://api.github.com/repos/flowck/all-contributors/issues/events{/number}",
  "events_url": "https://api.github.com/repos/flowck/all-contributors/events",
  "assignees_url": "https://api.github.com/repos/flowck/all-contributors/assignees{/user}",
  "branches_url": "https://api.github.com/repos/flowck/all-contributors/branches{/branch}",
  "tags_url": "https://api.github.com/repos/flowck/all-contributors/tags",
  "blobs_url": "https://api.github.com/repos/flowck/all-contributors/git/blobs{/sha}",
  "git_tags_url": "https://api.github.com/repos/flowck/all-contributors/git/tags{/sha}",
  "git_refs_url": "https://api.github.com/repos/flowck/all-contributors/git/refs{/sha}",
  "trees_url": "https://api.github.com/repos/flowck/all-contributors/git/trees{/sha}",
  "statuses_url": "https://api.github.com/repos/flowck/all-contributors/statuses/{sha}",
  "languages_url": "https://api.github.com/repos/flowck/all-contributors/languages",
  "stargazers_url": "https://api.github.com/repos/flowck/all-contributors/stargazers",
  "contributors_url": "https://api.github.com/repos/flowck/all-contributors/contributors",
  "subscribers_url": "https://api.github.com/repos/flowck/all-contributors/subscribers",
  "subscription_url": "https://api.github.com/repos/flowck/all-contributors/subscription",
  "commits_url": "https://api.github.com/repos/flowck/all-contributors/commits{/sha}",
  "git_commits_url": "https://api.github.com/repos/flowck/all-contributors/git/commits{/sha}",
  "comments_url": "https://api.github.com/repos/flowck/all-contributors/comments{/number}",
  "issue_comment_url": "https://api.github.com/repos/flowck/all-contributors/issues/comments{/number}",
  "contents_url": "https://api.github.com/repos/flowck/all-contributors/contents/{+path}",
  "compare_url": "https://api.github.com/repos/flowck/all-contributors/compare/{base}...{head}",
  "merges_url": "https://api.github.com/repos/flowck/all-contributors/merges",
  "archive_url": "https://api.github.com/repos/flowck/all-contributors/{archive_format}{/ref}",
  "downloads_url": "https://api.github.com/repos/flowck/all-contributors/downloads",
  "issues_url": "https://api.github.com/repos/flowck/all-contributors/issues{/number}",
  "pulls_url": "https://api.github.com/repos/flowck/all-contributors/pulls{/number}",
  "milestones_url": "https://api.github.com/repos/flowck/all-contributors/milestones{/number}",
  "notifications_url": "https://api.github.com/repos/flowck/all-contributors/notifications{?since,all,participating}",
  "labels_url": "https://api.github.com/repos/flowck/all-contributors/labels{/name}",
  "releases_url": "https://api.github.com/repos/flowck/all-contributors/releases{/id}",
  "deployments_url": "https://api.github.com/repos/flowck/all-contributors/deployments",
  "created_at": "2019-03-28T09:20:02Z",
  "updated_at": "2019-03-28T09:20:04Z",
  "pushed_at": "2019-03-25T21:08:05Z",
  "git_url": "git://github.com/flowck/all-contributors.git",
  "ssh_url": "git@github.com:flowck/all-contributors.git",
  "clone_url": "https://github.com/flowck/all-contributors.git",
  "svn_url": "https://github.com/flowck/all-contributors",
  "homepage": "https://allcontributors.org",
  "size": 15873,
  "stargazers_count": 0,
  "watchers_count": 0,
  "language": "HTML",
  "has_issues": false,
  "has_projects": true,
  "has_downloads": true,
  "has_wiki": false,
  "has_pages": false,
  "forks_count": 0,
  "mirror_url": null,
  "archived": false,
  "disabled": false,
  "open_issues_count": 0,
  "license": {
      "key": "mit",
      "name": "MIT License",
      "spdx_id": "MIT",
      "url": "https://api.github.com/licenses/mit",
      "node_id": "MDc6TGljZW5zZTEz"
  },
  "forks": 0,
  "open_issues": 0,
  "watchers": 0,
  "default_branch": "master"
}


Enter fullscreen mode Exit fullscreen mode

Challenging isn't it? Manually? No!

Generating interfaces from JSON objects

On VS Code, I use the extension Paste JSON as CODE, and it enables me to paste JSON as an interface, even one as large as the described above.

After you've installed it in your VS Code, follow the steps below:

  • Open the desired .ts where you would like to paste the interface;
  • Type the combination: CMD + SHIFT + P (macOS) or CTRL + SHIFT + P (Windows and Linux);
  • Search for Paste JSON as CODE and press ENTER;
  • A new input field will be displayed, paste the JSON code on it and press ENTER;
  • The last step is to review and edit the names of the generated interfaces according to your needs;

Pasting JSON as CODE

What can you do if you use another editor

I did a quick search for editors like Webstorm and Sublime Text, and unfortunately didn't find an extension that does the same. Maybe I didn't put enough effort into my search, however, the creators of Past JSON as CODE created an online editor where you can paste JSON code and get the equivalent interface.

Alt Text

Conclusion

I've been using Past JSON as CODE extension for a while, and one thing that saves me time is the fact that it generates the interfaces recursively on nested JSON objects, giving me access to its child interfaces on a single operation.

To close this post, I'd say:

Automate whenever you can, your mind should busy with non-trivial thoughts and decisions

References

Originally published at: https://changani.me/blog

Top comments (5)

Collapse
 
hgiudatto profile image
Hector

AWESOME

Collapse
 
vasiliy0s profile image
Vasiliy Telyatnikov

Thanks for the tip!

Collapse
 
alaa_courdova profile image
Alaa Courdova

this is Cooooooooool

Collapse
 
rhyuen profile image
Robert

I thought this was pretty handy. I've been thinking about how to handle this for a while. Thanks for posting!

Collapse
 
flowck profile image
Firmino Changani

Hi Robert, glad it help. I personally use it a lot when I am in doubt on how to express certain data structure into an interface.

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