codemix / babel-plugin-typecheck

Static and runtime type checking for JavaScript in the form of a Babel plugin.
MIT License
886 stars 44 forks source link

Does it perform static checks? #17

Closed zerkms closed 9 years ago

zerkms commented 9 years ago

I've taken the first example from http://flowtype.org/docs/five-simple-examples.html and it compiles down to

/***/ function(module, exports) {

    'use strict';

    function foo(x) {
        return x * 10;
    }

    foo('Hello, world!');

/***/ },

without any error messages in webpack watch log.

Whereas the second example from that page compiles as

/***/ function(module, exports) {

    'use strict';

    function foo(x, y) {
        var _ref;

        if (typeof x !== 'string') throw new TypeError('Value of argument \'x\' violates contract, expected string got ' + (x === null ? 'null' : x instanceof Object && x.constructor ? x.constructor.name : typeof x));
        if (typeof y !== 'number') throw new TypeError('Value of argument \'y\' violates contract, expected number got ' + (y === null ? 'null' : y instanceof Object && y.constructor ? y.constructor.name : typeof y));
        _ref = x.length * y;
        if (typeof _ref !== 'string') throw new TypeError('Function \'foo\' return value violates contract, expected string got ' + (_ref === null ? 'null' : _ref instanceof Object && _ref.constructor ? _ref.constructor.name : typeof _ref));
        return _ref;
    }

    foo('Hello', 42);

/***/ },

which is expected.

Does it mean the plugin does not perform static checks?

phpnode commented 9 years ago

@zerkms it does some static checks but it's not intended as a replacement for flow, rather a companion to it. We don't do type inference, and we don't check callsites because the current babel API rather limits our ability to do it usefully. If you don't annotate a function with type information, we don't modify the function at all.

It'll currently refuse to compile cases like this, where we know the return value definitely violates the contract:

function foo (): string {
  if (true) {
    return "foo"; // ok
  }
  else {
    return false; // SyntaxError
  }
}

Given your example, if we change it to:

function foo (x: string): string {
  return x * 10;
}

We'll get a runtime type error but it's not yet clever enough to do it at compile time. It's trivial to add so I'll leave this issue open until that gets fixed.

zerkms commented 9 years ago

I see. For some reason I thought it internally uses flow, but it's just another implementation for the same syntax.

Thanks.