Repository: gcanti/tcomb (js)

Issue:
Struct extension of a refinement of a struct does not use the correct displayName
### Version

3.2.21

### Expected behaviour

A struct extension of a refinement of a struct should use the passed displayName

### Actual behaviour

The struct extension uses the right typeName but interpolated into the default Refinement name format.

### Steps to reproduce

1. Define a struct type
1. Define a refinement of the struct type
1. Extend the refinement of the struct type, passing a name
1. See that the passed name is not used as the displayName

```js
const t = require('tcomb');

const Rectangle = t.struct({
  width: t.Number,
  height: t.Number
}, 'Rectangle');

const Square = t.refinement(Rectangle, ({width, height}) => width === height, 'Square');
const Box = t.struct.extend([Rectangle, {depth: t.Number}], 'Box');
const Column = t.struct.extend([Square, {depth: t.Number}], 'Column');
const Cube = t.refinement(Column, ({width, height, depth}) => width === height && width === depth, 'Cube');

console.log(Square.displayName); // Square
console.log(Box.displayName); // Box -> struct extension of struct uses the passed name
console.log(Column.displayName); // {Column | <function1>} -> falls back to getDefaultName of the refinement, but using the right typeName
console.log(Cube.displayName); // Cube

// a simple workaround is to manually set displayName
Column.displayName = 'Column';
console.log(Column.displayName); // Column
```

### Stack trace and console log

No error here, just not using the expected name. 

Thanks for tcomb!

Pull request:
Struct extension of a refinement of a struct does now the correct dis…
…playName, fix #297

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 346f9e6..aee7d67 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.24
+
+- **Bug Fix**
+  - Struct extension of a refinement of a struct now use the correct displayName, fix #297 (@gcanti)
+
 # v3.2.23
 
 - **Bug Fix**
diff --git a/lib/extend.js b/lib/extend.js
index 63754ac..583f8cb 100644
--- a/lib/extend.js
+++ b/lib/extend.js
@@ -8,10 +8,15 @@ var isObject = require('./isObject');
 var refinement = require('./refinement');
 var decompose = require('./decompose');
 
-function compose(predicates, unrefinedType) {
-  return predicates.reduce(function (type, predicate) {
+function compose(predicates, unrefinedType, name) {
+  var result = predicates.reduce(function (type, predicate) {
     return refinement(type, predicate);
   }, unrefinedType);
+  if (name) {
+    result.displayName = name;
+    result.meta.name = name;
+  }
+  return result;
 }
 
 function getProps(type) {
@@ -48,9 +53,12 @@ function extend(combinator, mixins, options) {
   });
   options = combinator.getOptions(options);
   options.defaultProps = mixin(defaultProps, options.defaultProps, true);
-  var result = compose(predicates, combinator(props, options));
+  var result = compose(predicates, combinator(props, {
+    strict: options.strict,
+    defaultProps: options.defaultProps
+  }), options.name);
   mixin(result.prototype, prototype);
   return result;
 }
 
-module.exports = extend;
\ No newline at end of file
+module.exports = extend;
diff --git a/package.json b/package.json
index 5d232b1..d3abcdf 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tcomb",
-  "version": "3.2.23",
+  "version": "3.2.24",
   "description": "Type checking and DDD for JavaScript",
   "main": "index.js",
   "typings": "index.d.ts",


Test patch:
diff --git a/test/extend.js b/test/extend.js
index 4bad0ea..734963f 100644
--- a/test/extend.js
+++ b/test/extend.js
@@ -257,7 +257,9 @@ describe('extend(combinator, mixins, [name])', function () {
       };
       var RoleStrict = t.refinement(Role, atLeastOne$);
 
-      var CompanyContact = t.struct.extend([PersonContactStrict, mixin]);
+      var CompanyContact = t.struct.extend([PersonContactStrict, mixin], 'CompanyContact');
+      assert.strictEqual(CompanyContact.displayName, 'CompanyContact');
+      assert.strictEqual(CompanyContact.meta.name, 'CompanyContact');
       assert.strictEqual(CompanyContact.meta.kind, 'subtype');
       assert.strictEqual(CompanyContact.meta.predicate, atLeastOne);
       assert.strictEqual(CompanyContact.meta.type.meta.kind, 'struct');