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

Some ideas about type reflection #21

Closed zerkalica closed 8 years ago

zerkalica commented 8 years ago

What about reflection types in runtime, for example:

function myFn(a: string): string {
 return a + '1'
}

transpiled to


import t from 'tcomb'

function myFn(a) {
  myFn.__$.in(a)
  var res = a + '1'
  myFn.__$.out(res)
  return res
}

myFn.__$ = {
  in: t.Str
  out: t.Str
}

Now we can easy parse types in runtime and extract some info, this bridge for React.proptypes. We can easily build plugins for working with types in runtime.

class AnyComponent extends React.Component {
   propTypes: {
      a: string
   }
}

transpile to

import t from 'tcomb'
class Any {
  $schema: t.struct({a: t.Str})
}

What about using https://github.com/gcanti/tcomb for type checking? Why tcomb? Because it's great runtime type specification. It's powerfull type assertion library with many types, which you reimplement internally in you plugin.

phpnode commented 8 years ago

I don't like the idea of depending on another module for this, people forget to install it, it's hard to keep up to date with the babel plugin version etc. I want to keep things simple and fast.

However, whether we should support some kind of reflection is a different question, we could do that without requiring an external lib. E.g.

function foo (a: string, b: string): Array<string> {
  return [a, b];
}

could compile to:

function foo (a, b) {
  return [a, b];
}
foo[Symbol.for('types')] = [["string", "string"], "Array<string>"];

Obviously it'd have to be optional.

zerkalica commented 8 years ago
  1. Run-time checking without external run-time library blow up you code - we can't reuse same constructions.
  2. What about reusing typecheck in external libraries, not only local project. When we produce babel compiled library and publish it to npm (example: https://github.com/zerkalica/immutable-di/blob/master/package.json#L19) ? I produce production-ready code with external sourcemaps.
  3. I don't want to parse all code in node_modules for each project. I want to compile my external library once and give to programmers option to use or not to use sourcemaps and to enable or to disable typechecking. Run-time checking must be optionally disabled in runtime via environment vars.
  4. Look at babel-runtime, it's very good practice to extract helpers. Example: https://github.com/seangenabe/delayer, Promises - is very fat abstraction, but they shared via babel-runtime.
  5. "hard to keep up to date" external library - it's strange, any application has many dependencies and just write correct version to package.json.
  6. https://github.com/shuhei/babel-plugin-type-assertion uses external library rtts_assert and you don't need include it in you scripts.
phpnode commented 8 years ago

We can reduce their size by generating specialized helper functions for each type we need to verify in a particular file. Most of the rest of the size is in the error message which is very tailored to the specific function and not reusable. The other advantage of this approach is that we get accurate stack traces which makes debugging very easy. This is not possible with a typecheck library, and I don't think that using one really buys us anything in practise.