gcanti / babel-plugin-tcomb

Babel plugin for static and runtime type checking using Flow and tcomb
MIT License
482 stars 22 forks source link

Compatibility between type recursion and babel's retainLines option #143

Open artkravchenko opened 7 years ago

artkravchenko commented 7 years ago

Hello.

I use tcomb (v3.2.15) and babel-plugin-tcomb (v0.3.21) with babel-loader (v6.2.7).

// .babelrc

{
  "presets": [
    "es2015",
    "react",
    "stage-1"
  ],
  "plugins": [
    ["lodash"]
  ],
  "retainLines": true
}

My babel-loader's query in webpack dev configuration:

{
  cacheDirectory: true,
  presets: [
    ['es2015', { "modules": false }],
    'react',
    'stage-1'
  ],
  plugins: [
    "tcomb",
    "transform-decorators-legacy"
  ],
  env: {
    development: {
      presets: ['react-hmre']
    }
  }
}

There's an error during webpack building:

ERROR in ./src/definitions/users.js
Module parse failed: /home/unexpected/work/libertysoil/node_modules/babel-loader/index.js?
{"cacheDirectory":true,"presets":[["es2015",{"modules":false}],"react","stage-1"],"plugins":
["tcomb","transform-decorators-legacy"],"env":{"development":{"presets":["react-
hmre"]}}}!/home/unexpected/work/libertysoil/src/definitions/users.js Unexpected token (125:24)
You may need an appropriate loader to handle this file type.
|   more: UserMore,
|   updated_at: _common.DateType,
|   username: Username }))function _assert(x, type, name) {function message() {return 'Invalid value ' 
+ _tcomb.default.stringify(x) + ' supplied to ' + name + ' (expected a ' + 
_tcomb.default.getTypeName(type) + ')';}if (_tcomb.default.isType(type)) {if (!type.is(x)) {type(x, [name 
+ ': ' + _tcomb.default.getTypeName(type)]);_tcomb.default.fail(message());}return type(x);}if (!(x 
instanceof type)) {_tcomb.default.fail(message());}return x;}
 @ ./src/api/client.js 31:13-44
 @ ./src/scripts/app.js
 @ multi main

The reason of problem is

// ./src/definitions/users.js

// importing DataType...
// defining Username, UserId, UserMore types...

// recursive
export type RawUser = {
  created_at: DateType,
  followers: Array<RawUser>,
  following: Array<RawUser>,
  fullName?: string,
  gravatarHash: string,
  id: UserId,
  more: UserMore,
  updated_at: DateType,
  username: Username
};

My configuration files can be a bit confusing. Let me edit them:

// .babelrc

{
  "presets": [
    "es2015",
    "react",
    "stage-1"
  ],
  "plugins": [
    ["lodash"]
  ],
  "retainLines": true,
  "env": {
    "development": {
      "plugins": [
        "syntax-flow",
        "tcomb",
        "transform-flow-strip-types",
        "transform-decorators-legacy"
      ]
    }
  }
}
// babel-loader's query
{
  cacheDirectory: true,
  env: {
    development: {
      presets: ['react-hmre']
    }
  }
}

And then the error is thrown right after npm start:

/home/unexpected/work/libertysoil/src/definitions/users.js:125
  username: Username }))function _assert(x, type, name) {function message() {return 'Invalid value ' + _tcomb.default.stringify(x) + ' supplied to ' + name + ' (expected a ' + _tcomb.default.getTypeName(type) + ')';}if (_tcomb.default.isType(type)) {if (!type.is(x)) {type(x, [name + ': ' + _tcomb.default.getTypeName(type)]);_tcomb.default.fail(message());}return type(x);}if (!(x instanceof type)) {_tcomb.default.fail(message());}return x;}
                        ^^^^^^^^
SyntaxError: Unexpected token function
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:528:28)
    at loader (/home/unexpected/work/libertysoil/node_modules/babel-cli/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.(anonymous function) [as .js] (/home/unexpected/work/libertysoil/node_modules/babel-cli/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/unexpected/work/libertysoil/src/definitions/posts.js:24:1)
    at Module._compile (module.js:556:32)
    at loader (/home/unexpected/work/libertysoil/node_modules/babel-cli/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.(anonymous function) [as .js] (/home/unexpected/work/libertysoil/node_modules/babel-cli/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)

Finally I've found if I remove retainLines: true from babel config, the problem disappears completely. It's surprising because I already use type recursion in my code and it works well without disabling retainLines option:

// recursive
export type Geotag = {
  admin?: Geotag,
  ...
}

Could you inspect the problem, please? Is my code correct? If yes, is it possible to fix this specific bug?

Thank you.