Back to home

Generating JSON Schema From Typescript Types main image

Generating JSON Schema From Typescript Types

This post will outline how you can use the ts-json-schema-generator package to generate a JSON schema from your TypeScript types.

Prerequisites

  1. A working repository with a TypeScript project.

Our code to generate the types

The script itself is written with JavaScript with the following code:

const tsj = require("ts-json-schema-generator"); const path = require("path"); const fs = require("fs"); const config = { path: path.join(__dirname, "../src/common/types/entities/api.ts"), tsconfig: path.join(__dirname, "../tsconfig.json"), type: "*", // Or <type-name> if you want to generate schema for that one type only }; const schema_path = path.join(__dirname, "../__generated__/schema.json"); function writeSchema(schema) { const schemaString = JSON.stringify(schema, null, 2); fs.writeFileSync(schema_path, schemaString); } function generateSchema() { return tsj.createGenerator(config).createSchema(config.type); } function main() { const output = generateSchema(); writeSchema(output); } main();

My script was locally kept in the scripts directory, which may help with the relative paths.

It would read a types file from src/common/types/entities/api.ts and the root tsconfig.json file.

The code does the following:

  1. Generates a schema using the configuration in config.
  2. Outputs that schema to __generated__/schema.json.

Note that it expected the __generated__ folder to already exist - you can change the code to do this automatically for you with the fs module if you would like.

In this example, I only wrote up a script in JavaScript (not TypeScript) that you may want to augment with your own code.

The types file

My target file src/common/types/entities/api.ts has the following:

type UserRole = "USER" | "SUPERUSER"; type User = { id: string; email: string | null; name: string | null; emailVerified: Date | null; image: string | null; role: UserRole; }; type Post = { id: string; createdAt: Date; updatedAt: Date; title: string; content: string | null; published: boolean; authorId: string; };

Running the script

If you run the script (in my case using node scripts/generate-schema.js), the following will be output to __generated__/schema.json:

{ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "User": { "type": "object", "properties": { "id": { "type": "string" }, "email": { "type": ["string", "null"] }, "name": { "type": ["string", "null"], "x-faker": "name.findName" }, "emailVerified": { "anyOf": [ { "type": "string", "format": "date-time" }, { "type": "null" } ] }, "image": { "type": ["string", "null"] }, "role": { "$ref": "#/definitions/UserRole" } }, "required": ["id", "email", "name", "emailVerified", "image", "role"], "additionalProperties": false, "description": "Model User" }, "UserRole": { "type": "string", "enum": ["USER", "SUPERUSER"], "description": "Enums" }, "Post": { "type": "object", "properties": { "id": { "type": "string" }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" }, "title": { "type": "string" }, "content": { "type": ["string", "null"] }, "published": { "type": "boolean" }, "authorId": { "type": "string" } }, "required": [ "id", "createdAt", "updatedAt", "title", "content", "published", "authorId" ], "additionalProperties": false, "description": "Model Post" } } }

Summary

Today's post demonstrated how to output a valid JSON schema using the package ts-json-schema-generator.

This can be useful in standardizing the JSON schema for your API based on a particular set of type definitions.

Resources and further reading

Photo credit: impatrickt

Personal image

Dennis O'Keeffe

@dennisokeeffe92
  • Melbourne, Australia

Hi, I am a professional Software Engineer. Formerly of Culture Amp, UsabilityHub, Present Company and NightGuru.
I am currently working on workingoutloud.dev, Den Dribbles and LandPad .

1,200+ PEOPLE ALREADY JOINED ❤️️

Get fresh posts + news direct to your inbox.

No spam. We only send you relevant content.