Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update documentation in regard to new Babel macro #30

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 73 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,27 @@ interfaces. It allows validating data, such as parsed JSON objects received
over the network, or parsed JSON or YAML files, to check if they satisfy a
TypeScript interface, and to produce informative error messages if they do not.

This package works together with [ts-interface-checker](https://github.com/gristlabs/ts-interface-checker).
You use `ts-interface-builder` in a build step that generates code for a runtime description of your interfaces.
You then use `ts-interface-checker` in your code to create validator functions from this runtime description.

These runtime descriptions come in the form of `ts-interface-checker` ["type suites"](https://github.com/gristlabs/ts-interface-checker#type-suites),
one per input TS file.

This package offers two ways to get generated "type suites" in your code:
1. CLI - Run a command to save generated type suites in new TS or JS files
2. Babel Macro *(advanced)* - Call a Babel macro function that returns a generated type suite

## Installation

```
npm install --save-dev ts-interface-builder
npm install --save ts-interface-checker
```

## Usage
## CLI Usage

This module works together with [ts-interface-checker](https://github.com/gristlabs/ts-interface-checker) module. You use
`ts-interface-builder` in a build step that converts some TypeScript interfaces
to a new TypeScript or JavaScript file (with `-ti.ts` or `-ti.js` extension) that provides a runtime
description of the interface. You then use `ts-interface-checker` in your
program to create validator functions from this runtime description.
**Run a command to save generated type suites in new TS or JS files**

```
`npm bin`/ts-interface-builder [options] <typescript-files...>
Expand Down Expand Up @@ -53,7 +60,7 @@ import * as t from "ts-interface-checker";

export const Square = t.iface([], {
"size": "number",
"color": t.opt("string"),
"color": t.opt("string")
});

const exportedTypeSuite: t.ITypeSuite = {
Expand All @@ -62,7 +69,65 @@ const exportedTypeSuite: t.ITypeSuite = {
export default exportedTypeSuite;
```

See [ts-interface-checker](https://github.com/gristlabs/ts-interface-checker) module for how to use this file in your program.
See [ts-interface-checker documentation](https://github.com/gristlabs/ts-interface-checker#readme) for how to use the exported type suite in your code.

## Babel Macro Usage

**Call a Babel macro function that returns a generated type suite**

This method requires your project to have [Babel](https://babeljs.io/docs/en/) and [`babel-plugin-macros`](https://github.com/kentcdodds/babel-plugin-macros) set up.
See installation instructions for each in their respective documentation.
Note that if you're using a Babel preset, you might unknowingly already have `babel-plugin-macros` set up.
For example, the popular [`babel-preset-react-app`](https://github.com/facebook/create-react-app/tree/master/packages/babel-preset-react-app)
already includes `babel-plugin-macros`.

With those things set up, in your code you can now just call the `getTypeSuite` macro function (exported from `ts-interface-builder/macro`) to get a type suite.
During your Babel build step, the required type suites will be generated and included in Babel's output.

For example, if you have a TypeScript file that defines some types:
```typescript
// foo.ts
interface Square {
size: number;
color?: string;
}
```

You can get a type suite for it in your code like this:
```typescript
import { getTypeSuite } from 'ts-interface-builder/macro';

const fooTypeSuite = getTypeSuite('./foo.ts', { /* options */ });
```

The code above would be transpiled into:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd skip this block. It's long, the details are mostly internal. How about something more illustrative. Maybe mention that the runtime description is generated from the interfaces found in './foo.ts', so that this becomes roughly equivalent to:

const fooTypeSuite = {
    Square: t.iface([], {
      "size": "number",
      "color": t.opt("string")
    })
  };

```js
import * as t from "ts-interface-checker";

function once(fn) {
var result;
return function () {
return result || (result = fn());
};
}

var typeSuite0 = once(function () {
return {
Square: t.iface([], {
"size": "number",
"color": t.opt("string")
})
};
});

var fooTypeSuite = typeSuite0();
```

See [ts-interface-checker documentation](https://github.com/gristlabs/ts-interface-checker#readme) for how to use the returned type suite in your code.

The `getCheckers` macro function is also exported, as a convenience, to get a checker suite (with validator functions) directly
instead of first getting a type suite and then creating a checker suite from it (using `ts-interface-checker`s `createCheckers` function).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd insert after "as a convenience" a colon and a code block with an example of how to call it, and a one-liner example how to use it.

As with `getTypeSuite`, repeated calls to `getCheckers` using the same arguments will return the same object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: "For both getTypeSuite and getCheckers, "...


## Limitations
This module currently does not support generics, except Promises. Promises are supported by unwrapping `Promise<T>` to simply `T`.
2 changes: 1 addition & 1 deletion lib/macro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const macroHandler: MacroHandler = (params) => {
if (!somePath) {
return;
}
const programPath = somePath.findParent((path) => path.isProgram());
const programPath = somePath.findParent((path) => path.isProgram())!;

const registry = new RequirementRegistry();
const toReplace = [
Expand Down