Repository: gcanti/io-ts-types
Pull request #87 (2019-03-11 21:11:34)

New Feature: add RegExp decoder


Patch:
diff --git a/docs/modules/regexp.ts.md b/docs/modules/regexp.ts.md
new file mode 100644
index 0000000..53c5412
--- /dev/null
+++ b/docs/modules/regexp.ts.md
@@ -0,0 +1,54 @@
+---
+title: regexp.ts
+nav_order: 26
+parent: Modules
+---
+
+---
+
+<h2 class="text-delta">Table of contents</h2>
+
+- [RegExpC (interface)](#regexpc-interface)
+- [RegExpType (class)](#regexptype-class)
+- [regexp (constant)](#regexp-constant)
+
+---
+
+# RegExpC (interface)
+
+**Signature**
+
+```ts
+export interface RegExpC extends RegExpType {}
+```
+
+# RegExpType (class)
+
+**Signature**
+
+```ts
+export class RegExpType {
+  constructor() { ... }
+  ...
+}
+```
+
+# regexp (constant)
+
+**Signature**
+
+```ts
+export const regexp: RegExpC = ...
+```
+
+**Example**
+
+```ts
+import { regexp } from 'io-ts-types/lib/regexp'
+import { right } from 'fp-ts/lib/Either'
+
+const input1 = /\w+/
+const input2 = new RegExp('\\w+')
+assert.deepStrictEqual(regexp.decode(input1), right(input1))
+assert.deepStrictEqual(regexp.decode(input2), right(input2))
+```
diff --git a/docs/modules/string/uuid.ts.md b/docs/modules/string/uuid.ts.md
index af002bd..dcccdf0 100644
--- a/docs/modules/string/uuid.ts.md
+++ b/docs/modules/string/uuid.ts.md
@@ -1,6 +1,6 @@
 ---
 title: string/uuid.ts
-nav_order: 26
+nav_order: 27
 parent: Modules
 ---
 
diff --git a/docs/modules/withMessage.ts.md b/docs/modules/withMessage.ts.md
index 5e83269..b4b1c95 100644
--- a/docs/modules/withMessage.ts.md
+++ b/docs/modules/withMessage.ts.md
@@ -1,6 +1,6 @@
 ---
 title: withMessage.ts
-nav_order: 27
+nav_order: 28
 parent: Modules
 ---
 
diff --git a/docs/modules/withValidate.ts.md b/docs/modules/withValidate.ts.md
index 10437d9..62f700b 100644
--- a/docs/modules/withValidate.ts.md
+++ b/docs/modules/withValidate.ts.md
@@ -1,6 +1,6 @@
 ---
 title: withValidate.ts
-nav_order: 28
+nav_order: 29
 parent: Modules
 ---
 
diff --git a/src/index.ts b/src/index.ts
index a4f54e7..19388a3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,6 +4,9 @@ export { DateFromISOString, DateFromISOStringC, DateFromISOStringType } from './
 export { DateFromNumber, DateFromNumberC, DateFromNumberType } from './Date/DateFromNumber'
 export { DateFromUnixTime, DateFromUnixTimeC, DateFromUnixTimeType } from './Date/DateFromUnixTime'
 
+// RegExp
+export { regexp, RegExpC, RegExpType } from './regexp'
+
 // fp-ts
 export { createEitherFromJSON, EitherFromJSONC, EitherFromJSONType } from './fp-ts/createEitherFromJSON'
 export {
diff --git a/src/regexp.ts b/src/regexp.ts
new file mode 100644
index 0000000..2bfd245
--- /dev/null
+++ b/src/regexp.ts
@@ -0,0 +1,27 @@
+import * as t from 'io-ts'
+
+export class RegExpType extends t.Type<RegExp, RegExp, unknown> {
+  readonly _tag: 'RegExpType' = 'RegExpType'
+  constructor() {
+    super(
+      'RegExp',
+      (u): u is RegExp => Object.prototype.toString.call(u) === '[object RegExp]',
+      (u, c) => (this.is(u) ? t.success(u) : t.failure(u, c)),
+      t.identity
+    )
+  }
+}
+
+export interface RegExpC extends RegExpType {}
+
+/**
+ * @example
+ * import { regexp } from 'io-ts-types/lib/regexp'
+ * import { right } from 'fp-ts/lib/Either'
+ *
+ * const input1 = /\w+/
+ * const input2 = new RegExp('\\w+')
+ * assert.deepStrictEqual(regexp.decode(input1), right(input1))
+ * assert.deepStrictEqual(regexp.decode(input2), right(input2))
+ */
+export const regexp: RegExpC = new RegExpType()


Test patch:
diff --git a/test/index.ts b/test/index.ts
index 3caafa3..1b98b0c 100644
--- a/test/index.ts
+++ b/test/index.ts
@@ -31,6 +31,7 @@ import {
   lensesFromProps,
   mapOutput,
   NumberFromString,
+  regexp,
   uuid,
   TypePrismIso
 } from '../src'
@@ -306,6 +307,17 @@ describe('Date', () => {
   })
 })
 
+describe('RegExp', () => {
+  it('should decode RegExp values', () => {
+    assert.deepEqual(regexp.decode(/\w+/), right(/\w+/))
+    assert.deepEqual(regexp.decode(new RegExp('\\w+')), right(new RegExp('\\w+')))
+  })
+
+  it('should not decode non-Date values', () => {
+    assert.deepEqual(PathReporter.report(regexp.decode(1)), ['Invalid value 1 supplied to : RegExp'])
+  })
+})
+
 describe('monocle-ts', () => {
   it('lensesFromProps', () => {
     const T1 = t.type({