Repository: gcanti/tcomb (js)

Issue:
fromJSON: typecasting of values inside t.intersection does not work
I think I have found a bug, unless I am missing something trivial.

### Version

3.2.12

### Expected behaviour
```
import t from 'tcomb';
import fromJSON from 'tcomb/lib/fromJSON';

t.Date.fromJSON = (x) => new Date(x);

const A = t.interface({ foo: t.String });
const B = t.interface({ bar: t.String });
const C = t.interface({ bar: t.Date });

const AB = t.intersection([A, B]);
const AC = t.intersection([A, C]);

const matchA = { foo: 'asd' };
const matchB = { bar: '2016-10-27T00:00:00.000+00:00' };
const matchBoth = Object.assign({}, matchA, matchB);

fromJSON(matchBoth, AB); // works as expected
fromJSON(matchB, C); // works as expected (and casts bar to a Date)
fromJSON(matchBoth, AC); // this should return me the deserialized json
```

### Actual behaviour

Last line in the example does not return the serialized JSON, but throws a type error instead

Pull request description:
fromJSON: typecasting of values inside `t.intersection`, fix #250

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 735798a..d2f0f7e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,11 @@
 **Note**: Gaps between patch versions are faulty/broken releases.
 **Note**: A feature tagged as Experimental is in a high state of flux, you're at risk of it changing without notice.
 
+# v3.2.13
+
+- **Bug Fix**
+  - fromJSON: typecasting of values inside `t.intersection`, fix #250 (@gcanti)
+
 # v3.2.12
 
 - **Bug Fix**
diff --git a/lib/fromJSON.js b/lib/fromJSON.js
index 1ed83b1..7edc7cd 100644
--- a/lib/fromJSON.js
+++ b/lib/fromJSON.js
@@ -6,6 +6,13 @@ var isObject = require('./isObject');
 var isArray = require('./isArray');
 var isType = require('./isType');
 var create = require('./create');
+var assign = require('./assign');
+
+function assignMany(values) {
+  return values.reduce(function (acc, v) {
+    return assign(acc, v);
+  }, {});
+}
 
 function fromJSON(value, type, path) {
   if (process.env.NODE_ENV !== 'production') {
@@ -126,7 +133,16 @@ function fromJSON(value, type, path) {
       }
       return ret;
 
-    default : // enums, irreducible, intersection
+    case 'intersection' :
+      var values = type.meta.types.map(function (type, i) {
+        return fromJSON(value, type, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + getTypeName(type)) : null ));
+      });
+      return type(
+        isObject(values[0]) ? assignMany(values) : value,
+        path
+      );
+
+    default : // enums, irreducible
       return type(value, path);
   }
 }
diff --git a/package.json b/package.json
index 2737c96..7dd9e4b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tcomb",
-  "version": "3.2.12",
+  "version": "3.2.13",
   "description": "Type checking and DDD for JavaScript",
   "main": "index.js",
   "typings": "index.d.ts",


Test patch:
diff --git a/test/fromJSON.js b/test/fromJSON.js
index 0332636..0b56a29 100644
--- a/test/fromJSON.js
+++ b/test/fromJSON.js
@@ -191,4 +191,17 @@ describe('fromJSON', function () {
     }, '[tcomb] Invalid value 1 supplied to {[key: String]: String}/a: String');
   });
 
+  it('should handle intersections', function () {
+    var A = t.inter({ foo: t.String });
+    var B = t.inter({ bar: Date });
+    var AB = t.intersection([A, B]);
+    var json = {
+      foo: 'asd',
+      bar: '2016-10-27T00:00:00.000+00:00'
+    };
+    assert.ok(fromJSON(json, AB).bar instanceof Date);
+    var I2 = t.intersection([t.Number, t.Number]);
+    assert.ok(typeof fromJSON(1, I2) === 'number');
+  });
+
 });