Den Dribbles

Align TypeScript Standards With JSON Schema

September 20, 2020

In my current work, I am looking at ways to try enforce particular standards across multiple and larger projects.

This means standards set across different languages that are flexible, extensible and kept up to date.

A few of my upcoming posts will looking into some of my spikes that I am doing to as investigation, starting with the json-schema-to-typescript library.

JSON Schema

What is JSON Schema? Here is a definition from the JSON Schema Org site:

JSON Schema is a powerful tool for validating the structure of JSON data.

The hope is that I can use tooling for JSON schema and Open API to help with structuring micro-services and providing “cheap” contract testing.

Setting up the project

mkdir json-schema-ts-spike
cd json-schema-ts-spike

# start a yarn project with default settings
yarn init -y
yarn add json-schema-to-typescript jsonschema

# setup files we will use
touch index.js book.json

Compiling From Source

In my example, I will opt to generate by reading in from a particular file.

const Validator = require("jsonschema").Validator
const { compile, compileFromFile } = require("json-schema-to-typescript")
const fs = require("fs")
const path = require("path")

const main = async () => {
  // validate the schema first
  const v = new Validator()

  // read the schema details
  const schemaFilepath = path.join(__dirname, "book.json")
  const bookSchema = JSON.parse(fs.readFileSync(schemaFilepath, "utf-8"))

  // read the example
  const exampleJsonFilepath = path.join(__dirname, "example.json")
  const exampleJson = JSON.parse(fs.readFileSync(exampleJsonFilepath, "utf-8"))

  v.addSchema(bookSchema, "/BookSchema")
  const validation = v.validate(exampleJson, bookSchema)

  if (validation.errors.length) {

  // compile from file
  const ts = await compileFromFile(schemaFilepath)
  fs.writeFileSync("book.d.ts", ts)


This will be all the code we need for our example.

The JSON Schema file

For this part, let’s model a basic book and a collection. We need to add some schema info the the book.json file.

I won’t go too deep into the modelling itself with JSON schema, but these are the definitions I am coming up with:

  "$schema": "",

  "definitions": {
    "user": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "preferredName": { "type": "string" },
        "age": { "type": "string" },
        "gender": { "enum": ["male", "female", "other"] }
      "required": ["name", "preferredName", "age", "gender"]
    "author": {
      "type": "object",
      "properties": {
        "allOf": [{ "$ref": "#/definitions/address" }]
  "type": "object",
  "properties": {
    "author": { "$ref": "#/definitions/author" },
    "title": { "type": "string" },
    "publisher": { "type": "string" }
  "required": ["author", "title", "publisher"]

The Book JSON

Let’s add some info to our basic example.json file that we can test against:

  "author": {
    "name": "Dennis O'Keeffe",
    "preferredName": "Dennis",
    "age": 28,
    "gender": "male"
  "title": "The Greatness Of Strict Schemas",
  "publisher": "Real Publisher (definitely not fake)"

Running Our Creation

Run node index.js from the root directory.

You will actually notice that I left a mistake in there! The following will log out:

> node index.js
  ValidationError {
    property: '',
    message: 'is not of a type(s) string',
    schema: { type: 'string' },
    instance: 28,
    name: 'type',
    argument: [ 'string' ],
    stack: ' is not of a type(s) string'

Our validation (or invalidation per se) was a success! We said in the schema that it should be a string but we received the number 28.

Head back to book.json and convert the value to type number. Now if we run it again node index.js again, we will get some success! We will even see our books.d.ts file has been written.

You might be wondering why I am writing this blog post in js to generate TypeScript types. Honestly, when I am doing spikes I normally just write quick scripts and keep out the fluff.

You will see the following is generated:

/* tslint:disable */
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.

export interface BookSchema {
  author: User
  title: string
  publisher: string
  [k: string]: unknown
export interface User {
  name: string
  preferredName: string
  age: number
  gender: "male" | "female" | "other"
  [k: string]: unknown

Great success! We now have a type for our schema that we can import in.

Resources and Further Reading

  1. jsonschema - GitHub
  2. JSON Schema - Structuring A Complex Schema

Image credit: Tony Pham

Related Articles

February 12, 2021

Use the Node debugger to visualise performance

February 12, 2021

Slowly introducing yourself to the world of generative art with this short introduction

February 02, 2021

See how you can get started with the VSCode debugger for Node.js applications

December 02, 2020

Have you ever wanted to build a UI Component Library with TypeScript and React? This blog post will take you through a straightforward set up that uses the bare minimum to get a working component library that you can re-use across your different React projects.

November 07, 2020

Learn how to create a test Stripe example, update that example and deploy to Vercel for a Stripe payment gateway, React 17, TypeScript 4 and Next.js 10

November 04, 2020

Use the TypeScript AWS CDK to deploy static sites to S3 with a CloudFront distribution and Route53 setup for a custom domain.

October 15, 2020

Using Webpack 5 to build lambdas for AWS deployments

September 30, 2020

A look into how you can run a cron job to self-destruct tweets

September 20, 2020

Generate strongly-typed models and serializers from JSON, JSON Schema

September 20, 2020

Prevent Breaking API Changes With OpenAPI And openapi-diff

A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter