Repository: gcanti/io-ts
Pull request #340 (2019-06-20 22:42:44)

version 1.10.1


Patch:
diff --git a/.travis.yml b/.travis.yml
index ee8a4a9..d2442b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,3 @@
 language: node_js
 node_js:
-  - "8"
-before_script:
-  - export DISPLAY=:99.0
-  - sh -e /etc/init.d/xvfb start
+  - '10'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0cefc7..c7c42df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,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.
 
+# 1.10.1
+
+- **Bug Fix**
+  - handle `strict`, `exact` and `refinement` codecs when optimizing tagged unions, fix #339 (@gcanti)
+
 # 1.10.0
 
 **Note**. `io-ts` depends on [`fp-ts`](https://github.com/gcanti/fp-ts), starting from `1.10.0` you must install `fp-ts` manually (`fp-ts` is now a `peerDependency`)
diff --git a/package.json b/package.json
index 4b4591f..28788c1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "io-ts",
-  "version": "1.10.0",
+  "version": "1.10.1",
   "description": "TypeScript compatible runtime type system for IO validation",
   "files": [
     "lib",
diff --git a/src/index.ts b/src/index.ts
index 59d56aa..69ac5ce 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2053,6 +2053,20 @@ function isTypeC(codec: Any): codec is TypeC<Props> {
   return (codec as any)._tag === 'InterfaceType'
 }
 
+// tslint:disable-next-line: deprecation
+function isStrictC(codec: Any): codec is StrictC<Props> {
+  return (codec as any)._tag === 'StrictType'
+}
+
+function isExactC(codec: Any): codec is ExactC<HasProps> {
+  return (codec as any)._tag === 'ExactType'
+}
+
+// tslint:disable-next-line: deprecation
+function isRefinementC(codec: Any): codec is RefinementC<Any> {
+  return (codec as any)._tag === 'RefinementType'
+}
+
 function isIntersectionC(codec: Any): codec is IntersectionC<[Mixed, Mixed, ...Array<Mixed>]> {
   return (codec as any)._tag === 'IntersectionType'
 }
@@ -2074,7 +2088,7 @@ export function getTags(codec: Any): Tags {
   if (codec === lazyCodec) {
     return emptyTags
   }
-  if (isTypeC(codec)) {
+  if (isTypeC(codec) || isStrictC(codec)) {
     let index: Tags = emptyTags
     // tslint:disable-next-line: forin
     for (let k in codec.props) {
@@ -2087,6 +2101,8 @@ export function getTags(codec: Any): Tags {
       }
     }
     return index
+  } else if (isExactC(codec) || isRefinementC(codec)) {
+    return getTags(codec.type)
   } else if (isIntersectionC(codec)) {
     return codec.types.reduce((tags, codec) => mergeTags(tags, getTags(codec)), emptyTags)
   } else if (isUnionC(codec)) {


Test patch:
diff --git a/test/union.ts b/test/union.ts
index 6f95e8a..7f7e9e4 100644
--- a/test/union.ts
+++ b/test/union.ts
@@ -147,6 +147,39 @@ describe('union', () => {
       })
     })
 
+    it('strict', () => {
+      assert.strictEqual(t.getTags(t.strict({ a: t.string })), t.emptyTags)
+      assert.deepStrictEqual(t.getTags(t.strict({ tag: t.literal('a') })), { tag: ['a'] })
+      assert.deepStrictEqual(t.getTags(t.strict({ tag: t.literal('a'), type: t.literal('b') })), {
+        tag: ['a'],
+        type: ['b']
+      })
+    })
+
+    it('exact', () => {
+      assert.strictEqual(t.getTags(t.exact(t.type({ a: t.string }))), t.emptyTags)
+      assert.deepStrictEqual(t.getTags(t.exact(t.type({ tag: t.literal('a') }))), { tag: ['a'] })
+      assert.deepStrictEqual(t.getTags(t.exact(t.type({ tag: t.literal('a'), type: t.literal('b') }))), {
+        tag: ['a'],
+        type: ['b']
+      })
+    })
+
+    it('refinement', () => {
+      // tslint:disable-next-line: deprecation
+      assert.strictEqual(t.getTags(t.refinement(t.type({ a: t.string }), () => true)), t.emptyTags)
+      // tslint:disable-next-line: deprecation
+      assert.deepStrictEqual(t.getTags(t.refinement(t.type({ tag: t.literal('a') }), () => true)), { tag: ['a'] })
+      assert.deepStrictEqual(
+        // tslint:disable-next-line: deprecation
+        t.getTags(t.refinement(t.type({ tag: t.literal('a'), type: t.literal('b') }), () => true)),
+        {
+          tag: ['a'],
+          type: ['b']
+        }
+      )
+    })
+
     it('intersection', () => {
       assert.strictEqual(t.getTags(t.intersection([t.type({ a: t.string }), t.type({ b: t.number })])), t.emptyTags)
       assert.deepStrictEqual(t.getTags(t.intersection([t.type({ a: t.literal('a') }), t.type({ b: t.number })])), {