UNPKG

4.91 kBMarkdownView Raw
1# Babel Typecheck
2
3This is a [Babel](https://babeljs.io/) plugin for static and runtime type checking using [flow type](http://flowtype.org/) annotations.
4
5[![Build Status](https://travis-ci.org/codemix/babel-plugin-typecheck.svg)](https://travis-ci.org/codemix/babel-plugin-typecheck)
6
7> Note: Now requires babel 6.1, babel 5 users [see the 2.0 tag](https://github.com/codemix/babel-plugin-typecheck/tree/2.0.0).
8
9# What?
10
11Turns code like this:
12```js
13function sendMessage (to: User, message: string): boolean {
14 return socket.send(to, message);
15}
16```
17into code like this:
18```js
19function sendMessage(to, message) {
20 var _socket$send;
21
22 if (!(to instanceof User)) throw new TypeError("Value of argument 'to' violates contract.");
23 if (typeof message !== "string") throw new TypeError("Value of argument 'message' violates contract.");
24 _socket$send = socket.send(to, message);
25 if (typeof _socket$send !== "boolean") throw new TypeError("Function 'sendMessage' return value violates contract.");
26 return _socket$send;
27}
28```
29
30And guards against some silly mistakes, for example the following code will fail to compile with a `SyntaxError`, because the function can return the wrong type.
31
32```js
33function foo (): boolean {
34 if (Math.random() > 0.5) {
35 return "yes"; // <-- SyntaxError - string is not boolean
36 }
37 else {
38 return false;
39 }
40}
41
42function bar (input: string = 123): string { // <-- SyntaxError: default value is not string
43 return input + "456";
44}
45```
46
47# Examples
48
49The basic format is similar to [Flow Type Annotations](http://flowtype.org/docs/type-annotations.html).
50
51Here are a few examples of annotations this plugin supports:
52
53```js
54function foo(
55 aNum: number,
56 anOptionalString: ?string, // will allow null/undefined
57 anObject: Object,
58 aDate: Date,
59 anError: Error,
60 aUnionType: Object|string,
61 aClass: User,
62 aShape: {foo: number, bar: ?string},
63 anArray: Array,
64 arrayOf: string[] | Array<string>,
65 {x, y}: {x: string, y: number}, // destructuring works
66 es6Defaults: number = 42
67) : number {
68 return aNum;
69}
70```
71
72# Optimization
73
74In cases where typecheck can statically verify that the return value is of the correct type, no type checks will be inserted, for instance:
75```js
76function bar (): string|Object {
77 if (Math.random() > 0.5) {
78 return "yes";
79 }
80 else {
81 return {
82 message: "no"
83 };
84 }
85}
86```
87will produce no type checks at all, because we can trivially tell that the function can only return one of the two permitted types.
88This is also true for simple cases like:
89```js
90function createUser (): User {
91 return new User(); // <-- no typecheck required
92}
93```
94This is currently quite limited though, as the plugin can only statically infer the types of literals and very simple expressions, it can't (yet) statically verify e.g. the result of a function call. In those cases a runtime type check is required:
95```js
96function createUser (): User {
97 return User.create(); // <-- produces runtime typecheck
98}
99```
100
101
102## Changes in 3.0.0
103
104### Supports type aliases:
105```js
106type Foo = string|number;
107
108function demo (input: Foo): string {
109 return input + ' world';
110}
111
112demo('hello'); // ok
113demo(123); // ok
114demo(["not", "a", "Foo"]); // fails
115```
116
117### Better static type inference
118```js
119function demo (input: string): string[] {
120 return makeArray(input); // no return type check required, knows that makeArray is compatible
121}
122
123function makeArray (input: string): string[] {
124 return [input];
125}
126```
127
128### Type propagation
129```js
130function demo (input: string): User {
131 const user = new User({name: input});
132 return user; // No check required, knows that user is the correct type
133}
134```
135
136### Assignment tracking
137```js
138let name: string = "bob";
139
140name = "Bob"; // ok
141name = makeString(); // ok
142name = 123; // SyntaxError, expected string not number
143
144function makeString (): string {
145 return "Sally";
146}
147```
148
149### Type casting
150```js
151let name: string = "bob";
152
153name = "Bob";
154((name: number) = 123);
155name = 456;
156name = "fish"; // SyntaxError, expected number;
157```
158
159### Array type parameters
160```js
161function demo (input: string[]): number {
162 return input.length;
163}
164
165demo(["a", "b", "c"]); // ok
166demo([1, 2, 3]); // TypeError
167```
168
169### Shape tracking
170```js
171type User = {
172 name: string;
173 email: string;
174};
175
176function demo (input: User): string {
177 return input.name;
178}
179
180demo({}); // TypeError
181demo({name: 123, email: "test@test.com"}); // TypeError
182demo({name: "test", email: "test@test.com"}); // ok
183```
184
185# Installation
186
187First, install via [npm](https://npmjs.org/package/babel-plugin-typecheck).
188```sh
189npm install --save-dev babel-plugin-typecheck
190```
191Then, in your babel configuration (usually in your `.babelrc` file), add `"typecheck"` to your list of plugins:
192```json
193{
194 "plugins": ["typecheck"]
195}
196```
197
198
199# License
200
201Published by [codemix](http://codemix.com/) under a permissive MIT License, see [LICENSE.md](./LICENSE.md).
202