Skip to content

Commit

Permalink
Better docs, adding Parse helper function for consistency w/ paper an…
Browse files Browse the repository at this point in the history
…d ease-of-use.
  • Loading branch information
John Vilk committed Dec 18, 2016
1 parent 7964ed8 commit e239923
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
35 changes: 22 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# MakeTypes
# MakeTypes 1.0.0

> Make TypeScript types and proxy objects from example JSON objects. Can use proxy objects to dynamically type check JSON at runtime.
> Generate TypeScript types and proxy classes from example JSON objects. Type check JSON objects at runtime!
With MakeTypes, you can interact with REST endpoints and other sources of JSON with confidence that the fields you need are present on the JSON
object. MakeTypes generates proxies that enforce JSON types at runtime.
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.**

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.

All you need is a file containing sample JSON objects.

## Install

Expand All @@ -15,7 +20,7 @@ All you need is a file containing sample JSON objects.

npm install

## Usage
## Usage (General Ca)

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.

Expand All @@ -33,8 +38,9 @@ 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 static type.
They also standardize optional/nullable fields to contain `null` rather than `null` or `undefined`.
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`:

Expand Down Expand Up @@ -87,22 +93,23 @@ Example TypeScript code using proxy class:
```typescript
import {RootNameProxy} from './proxies';

const rawJson = JSON.parse('{"foo": "bar"}');
// RootName.Create will throw an exception if rawJson does not match the type of RootName.
const proxyObject = RootNameProxy.Create(rawJson);
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
let baz = proxyObject.baz; // TypeScript knows baz is number | null. In this case, it will be null.
```

### Using Interfaces

For a lighterweight option that provides no runtime guarantees, MakeTypes can also generate TypeScript interfaces that describe the expected structure of
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`:

```json
Expand Down Expand Up @@ -137,10 +144,12 @@ 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 thinks that baz is number | null, but it could also be undefined...
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#"](https://dl.acm.org/citation.cfm?id=2908115).
Since JavaScript/TypeScript lacks a distinction between integer and floating point types, we merge the `float` and `int` types into a `number` type.

At the moment, MakeTypes does not implement labelled top shapes. We plan to address this limitation in the next release.
3 changes: 3 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ export class CRecordShape {
this.forEachField((t, name) => {
w.tab(1).writeln(`public readonly ${name}: ${t.getProxyType(e)};`);
});
w.tab(1).writeln(`public static Parse(d: string): ${this.getProxyType(e)} {`);
w.tab(2).writeln(`return ${this.getProxyClass(e)}.Create(JSON.parse(d));`);
w.tab(1).writeln(`}`);
w.tab(1).writeln(`public static Create(d: any): ${this.getProxyType(e)} {`);
w.tab(2).writeln(`if (d === null || d === undefined) {`);
w.tab(3);
Expand Down

0 comments on commit e239923

Please sign in to comment.