• Stars
    star
    455
  • Rank 96,175 (Top 2 %)
  • Language
    TypeScript
  • Created almost 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Make TypeScript types and proxy objects from example JSON objects. Can use proxy objects to dynamically type check JSON at runtime.

MakeTypes 1.1.2

Generate TypeScript types and proxy classes from example JSON objects. Type check JSON objects at runtime!

NPM version Build Status Coverage Status

With MakeTypes, you can interact with REST endpoints and other sources of JSON with confidence that your program receives the data you expect. All you need is a file containing representative sample JSON objects.

Try the web demo!

Features:

  • Type-checked JSON.parse. Proxy classes generated with MakeTypes will parse your JSON and check that it matches the expected type during runtime.
  • Statically type-check code that interacts with JSON objects. Proxy objects generated with MakeTypes are expressed as TypeScript classes, so you can statically type check that your code is appropriately accessing fields on the JSON object.
  • Generate TypeScript interfaces to describe JSON types. Don't want the overhead of runtime type checking, and trust that your samples are representative? You can opt to generate TypeScript interfaces instead, which describe the expected structure of the JSON object and facilitate type checking.

Install

npm i -g maketypes

Build

npm install

Usage

First, write a file called samples.json that contains JSON samples for a particular object type, such as the value returned from a web service. It can either contain a single sample or an array of samples.

Then, run:

make_types -i interfaces.ts -p proxies.ts samples.json RootName

...where:

  • interfaces.ts will hold interface definitions for the JSON (optional)
  • proxies.ts will hold proxy class definitions that you can use to dynamically type check JSON objects at runtime (optional)
  • RootName specifies the name to use for the type that describes the JSON object

MakeTypes will use simple heuristics to determine the names of nested sub-types.

Using Proxies

MakeTypes generates proxy classes that dynamically check that runtime JSON objects match the expected static type. They also standardize optional/nullable fields to contain null rather than null or undefined, which simplifies your code.

Example samples.json:

[
  {
    "foo": "lalala"
  },
  {
    "foo": "hello",
    "baz": 32
  }
]

Generation command:

make_types -p proxies.ts samples.json RootName

Proxy generated from example:

export class RootNameProxy {
  public readonly foo: string;
  public readonly baz: number | null;
  public static Parse(d: string): RootNameProxy {
    return RootNameProxy.Create(JSON.parse(d));
  }
  public static Create(d: any): RootNameProxy {
    if (d === null || d === undefined) {
      throwNull2NonNull("RootName");
    } else if (typeof(d) !== 'object') {
      throwNotObject("RootName");
    } else if (Array.isArray(d)) {
      throwIsArray("RootName");
    }
    return new RootNameProxy(d);
  }
  private constructor(d: any) {
    checkString(d.foo, false);
    this.foo = d.foo;
    checkNumber(d.baz, true);
    if (d.baz === undefined) {
      d.baz = null;
    }
    this.baz = d.baz;
  }
}

Example TypeScript code using proxy class:

import {RootNameProxy} from './proxies';

// RootName.Create will throw an exception if rawJson does not match the type of RootName.
const proxyObject = RootNameProxy.Parse('{"foo": "bar"}');
// Now, you can access all of the properties of the JSON object with confidence that they
// actually exist.
let foo = proxyObject.foo; // TypeScript knows foo is a string
// If one of the properties on the proxy is optional, then it will have a null value.
let baz = proxyObject.baz; // TypeScript knows baz is number | null. In this case, it will be null.

Using Interfaces

For a lighterweighter option that provides no runtime guarantees, MakeTypes can also generate TypeScript interfaces that describe the expected structure of JSON objects. You can use these interfaces to typecheck code that interacts with JSON objects, but they cannot check if the JSON objects obey the static type at runtime.

Interfaces also succinctly express the static type that MakeTypes is inferring from your samples, so this feature can be a good debugging mechanism.

Example samples.json:

[
  {
    "foo": "lalala"
  },
  {
    "foo": "hello",
    "baz": 32
  }
]

Generation command:

make_types -i interfaces.ts samples.json RootName

Interface generated from example:

export interface RootName {
  foo: string;
  baz?: number | null;
}

Example TypeScript code using interfaces:

import {RootName} from './interfaces';

const rawJson = <RootName> JSON.parse('{"foo": "bar"}');
let foo = rawJson.foo; // TypeScript knows foo i a string
let baz = rawJson.baz; // TypeScript knows that baz is an optional field that may not be there.

Inspiration / Technique

MakeTypes uses the Common Preferred Shape Relation from Petricek et al.'s PLDI 2016 paper, "Types from Data: Making Structured Data First-Class Citizens in F#". Since JavaScript/TypeScript lacks a distinction between integer and floating point types, we merge the float and int types into a number type.

More Repositories

1

BrowserFS

BrowserFS is an in-browser filesystem that emulates the Node JS filesystem API and supports storing and retrieving files from various backends.
TypeScript
3,075
star
2

mitmproxy-node

A bridge between Python's mitmproxy and Node.JS programs. Rewrite network requests using Node.JS!
TypeScript
92
star
3

jarjvm

JAR JVM is a Java Virtual Machine interpreter written completely in JavaScript. It allows you to run your Java programs in the browser, no plugins required!
JavaScript
28
star
4

DotWriter

DotWriter is a C++ API for creating DOT files for use with tools such as GraphViz.
C++
12
star
5

locate-java-home

Locates JAVA_HOME on any platform, and can differentiate between different versions.
TypeScript
12
star
6

merge-source-maps

Library, command-line tool, and Grunt task for merging multiple source maps from compilation phases into a single source map.
TypeScript
11
star
7

browserfs-zipfs-extras

Adds EXPLODE, UNSHRINK, and UNREDUCE support to BrowserFS's ZipFS.
TypeScript
11
star
8

JumboTron

Combines multiple independent canvases on a web page into one logical canvas! Your application won't even know it.
JavaScript
8
star
9

node-ar

A Node library for reading Unix archive files.
8
star
10

bfs-process

An emulation of NodeJS's process variable for the browser. Used in BrowserFS.
TypeScript
5
star
11

WeChat

A repository of shared resources for the WeChat Distributed Chat System project for CMPSCI 691 at UMass Amherst.
4
star
12

doppio-demo

Demo of the Doppio Runtime System.
Java
4
star
13

bfs-buffer

An emulation of NodeJS's Buffer module. Used in BrowserFS.
TypeScript
3
star
14

bfs-path

An emulation of Node's path module. Used in BrowserFS.
TypeScript
3
star
15

doppio-benchmarks

Benchmarks for DoppioJVM.
Java
2
star
16

dropbox-sdk-examples-ts

Dropbox SDK examples in TypeScript.
JavaScript
2
star
17

rollup-plugin-esnext

Convert CommonJS modules to ES2015 using esnext
JavaScript
2
star
18

bfs-browserify-test

A simple test that BrowserFS's modules work appropriately with Browserify.
JavaScript
1
star
19

bfs-fs

An implementation of NodeJS's fs module in the browser. Thin wrapper around BrowserFS.
JavaScript
1
star