Upgrade io-ts and fp-ts to 2.0.0

Change-type: minor
Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
Cameron Diver 2019-09-05 14:38:21 +01:00
parent 5ce8ba8acf
commit 9843f62e24
6 changed files with 184 additions and 126 deletions

201
package-lock.json generated
View File

@ -1564,7 +1564,7 @@
"fetch-ponyfill": "^4.0.0",
"fetch-readablestream": "^0.2.0",
"lodash": "^4.6.1",
"node-web-streams": "github:resin-io-modules/node-web-streams#emit-errors",
"node-web-streams": "github:resin-io-modules/node-web-streams#46f98300b69090bde3f6b4983877ccfe283a892c",
"progress-stream": "^2.0.0",
"qs": "^6.3.0",
"rindle": "^1.3.1"
@ -1700,7 +1700,7 @@
"lodash": "^4.13.1",
"resin-cli-form": "^1.4.1",
"resin-cli-visuals": "^1.2.8",
"resin-discoverable-services": "git+https://github.com/resin-io-modules/resin-discoverable-services.git#find-on-all-interfaces",
"resin-discoverable-services": "git+https://github.com/resin-io-modules/resin-discoverable-services.git#afca9e4700ec5ef82aa897f14bd5a46f06518061",
"resin-semver": "^1.4.0",
"revalidator": "^0.3.1",
"rindle": "^1.3.0",
@ -1951,7 +1951,7 @@
"deep-equal": "^1.0.1",
"dns-equal": "^1.0.0",
"dns-txt": "^2.0.2",
"multicast-dns": "git+https://github.com/resin-io-modules/multicast-dns.git#listen-on-all-interfaces",
"multicast-dns": "git+https://github.com/resin-io-modules/multicast-dns.git#a15c63464eb43e8925b187ed5cb9de6892e8aacc",
"multicast-dns-service-types": "^1.1.0"
}
},
@ -3001,10 +3001,18 @@
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
"integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
"dev": true,
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
"is-regex": "^1.0.4",
"object-is": "^1.0.1",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.2.0"
}
},
"deep-extend": {
"version": "0.6.0",
@ -3049,6 +3057,15 @@
"clone": "^1.0.2"
}
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
"requires": {
"object-keys": "^1.0.12"
}
},
"define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
@ -4473,8 +4490,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -4495,14 +4511,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4517,20 +4531,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -4647,8 +4658,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -4660,7 +4670,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -4675,7 +4684,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -4683,14 +4691,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -4709,7 +4715,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -4790,8 +4795,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -4803,7 +4807,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4889,8 +4892,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -4926,7 +4928,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4946,7 +4947,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -4990,14 +4990,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
}
}
},
@ -5077,9 +5075,9 @@
"dev": true
},
"fp-ts": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.13.0.tgz",
"integrity": "sha512-QDPtCkuLay+dX3zinnvt0ER+j8mdWZZSpM//DIY3GycgwUTDPBKFD7CxX5DU/mIDstcWqGuuUSrMNtB6MWluCQ==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.0.5.tgz",
"integrity": "sha512-opI5r+rVlpZE7Rhk0YtqsrmxGkbIw0dRNqGca8FEAMMnjomXotG+R9QkLQg20onx7R8qhepAn4CCOP8usma/Xw==",
"dev": true
},
"fragment-cache": {
@ -5156,6 +5154,12 @@
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"g-status": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz",
@ -5538,6 +5542,15 @@
"har-schema": "^2.0.0"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@ -6167,12 +6180,33 @@
"dev": true
},
"io-ts": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.6.4.tgz",
"integrity": "sha512-n/a3RiOdsgni4sjsYVtny6/PmzVfU3Gtkc1O06izREueu6NkP57olLa7oACUT+F2LIDnePXY2HA4wxGYqHI05A==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz",
"integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==",
"dev": true
},
"io-ts-reporters": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/io-ts-reporters/-/io-ts-reporters-1.0.0.tgz",
"integrity": "sha512-jjMvTnFYYxX3ue3cajmqCAf7sM4+lFvaaUuAL+otJv2DE+WDxYvQeCcUYveoq37rVSftJHZBEOrnvz3x0VdRXA==",
"dev": true,
"requires": {
"fp-ts": "^1.0.0"
"fp-ts": "^2.0.2",
"io-ts": "^2.0.0"
},
"dependencies": {
"fp-ts": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.0.5.tgz",
"integrity": "sha512-opI5r+rVlpZE7Rhk0YtqsrmxGkbIw0dRNqGca8FEAMMnjomXotG+R9QkLQg20onx7R8qhepAn4CCOP8usma/Xw==",
"dev": true
},
"io-ts": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz",
"integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==",
"dev": true
}
}
},
"ip": {
@ -6217,6 +6251,12 @@
}
}
},
"is-arguments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
"dev": true
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@ -6275,6 +6315,12 @@
}
}
},
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
"dev": true
},
"is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
@ -6418,6 +6464,15 @@
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"dev": true,
"requires": {
"has": "^1.0.1"
}
},
"is-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
@ -8555,6 +8610,18 @@
"integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==",
"dev": true
},
"object-is": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
"integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
"dev": true
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
},
"object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@ -9450,6 +9517,15 @@
"safe-regex": "^1.1.0"
}
},
"regexp.prototype.flags": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
"integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
"dev": true,
"requires": {
"define-properties": "^1.1.2"
}
},
"relative": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/relative/-/relative-3.0.2.tgz",
@ -9645,7 +9721,7 @@
"dev": true,
"requires": {
"bluebird": "^3.0.0",
"bonjour": "git+https://github.com/resin-io/bonjour.git#fixed-mdns",
"bonjour": "git+https://github.com/resin-io/bonjour.git#e018851dc823b4b3f670f658f71d0c1c7f3e637c",
"ip": "^1.1.4",
"lodash": "^4.17.4"
}
@ -11788,8 +11864,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -11817,7 +11892,6 @@
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -11832,8 +11906,7 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
@ -11844,8 +11917,7 @@
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -11962,8 +12034,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -11975,7 +12046,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -11990,7 +12060,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -11998,14 +12067,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -12024,7 +12091,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -12105,8 +12171,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -12118,7 +12183,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -12204,8 +12268,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -12241,7 +12304,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -12261,7 +12323,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -12305,14 +12366,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
}
}
},

View File

@ -79,9 +79,10 @@
"event-stream": "3.3.4",
"express": "^4.0.0",
"fork-ts-checker-webpack-plugin": "^0.5.2",
"fp-ts": "^1.12.2",
"fp-ts": "^2.0.0",
"husky": "^1.3.0",
"io-ts": "^1.5.1",
"io-ts": "^2.0.1",
"io-ts-reporters": "^1.0.0",
"istanbul": "^0.4.5",
"json-mask": "^0.3.8",
"knex": "~0.15.2",

View File

@ -408,9 +408,9 @@ export class APIBinder {
);
}
return {
id: id.value,
name: name.value,
value: value.value,
id: id.right,
name: name.right,
value: value.right,
};
});
}

View File

@ -1,6 +1,7 @@
import * as Bluebird from 'bluebird';
import * as Dockerode from 'dockerode';
import { EventEmitter } from 'events';
import { isLeft } from 'fp-ts/lib/Either';
import * as JSONStream from 'JSONStream';
import * as _ from 'lodash';
import { fs } from 'mz';
@ -326,14 +327,14 @@ export class ServiceManager extends (EventEmitter as new () => ServiceManagerEve
// Get the statusCode from the original cause and make sure it's
// definitely an int for comparison reasons
const maybeStatusCode = PermissiveNumber.decode(e.statusCode);
if (maybeStatusCode.isLeft()) {
if (isLeft(maybeStatusCode)) {
remove = true;
err = new Error(
`Could not parse status code from docker error: ${e}`,
);
throw err;
}
const statusCode = maybeStatusCode.value;
const statusCode = maybeStatusCode.right;
const message = e.message;
// 304 means the container was already started, precisely what we want
@ -568,12 +569,12 @@ export class ServiceManager extends (EventEmitter as new () => ServiceManagerEve
// Get the statusCode from the original cause and make sure it's
// definitely an int for comparison reasons
const maybeStatusCode = PermissiveNumber.decode(e.statusCode);
if (maybeStatusCode.isLeft()) {
if (isLeft(maybeStatusCode)) {
throw new Error(
`Could not parse status code from docker error: ${e}`,
);
}
const statusCode = maybeStatusCode.value;
const statusCode = maybeStatusCode.right;
// 304 means the container was already stopped, so we can just remove it
if (statusCode === 304) {

View File

@ -6,7 +6,7 @@ import { generateUniqueKey } from 'resin-register-device';
import StrictEventEmitter from 'strict-event-emitter-types';
import { inspect } from 'util';
import { Either } from 'fp-ts/lib/Either';
import { Either, isLeft, isRight, Right } from 'fp-ts/lib/Either';
import * as t from 'io-ts';
import ConfigJsonConfigBackend from './configJson';
@ -84,16 +84,19 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
undefined,
);
this.checkValueDecode(maybeDecoded, key, undefined);
return maybeDecoded.value;
return (
this.checkValueDecode(maybeDecoded, key, undefined) &&
maybeDecoded.right
);
}
return defaultValue as SchemaReturn<T>;
}
const decoded = this.decodeSchema(schemaKey, value);
this.checkValueDecode(decoded, key, value);
return decoded.value;
// The following function will throw if the value
// is not correct, so we chain it this way to keep
// the type system happy
return this.checkValueDecode(decoded, key, value) && decoded.right;
});
} else if (FnSchema.fnSchema.hasOwnProperty(key)) {
const fnKey = key as FnSchema.FnSchemaKey;
@ -105,9 +108,7 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
return promiseValue.then((value: unknown) => {
const decoded = schemaTypes[key].type.decode(value);
this.checkValueDecode(decoded, key, value);
return decoded.value as SchemaReturn<T>;
return this.checkValueDecode(decoded, key, value) && decoded.right;
});
} else {
throw new Error(`Unknown config value ${key}`);
@ -147,7 +148,6 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
throw new Error(
`Unknown configuration source: ${source} for config key: ${k}`,
);
break;
}
});
@ -181,7 +181,8 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
};
return Bluebird.try(() => {
// Firstly validate and coerce all of the types as they are being set
// Firstly validate and coerce all of the types as
// they are being set
keyValues = this.validateConfigMap(keyValues);
if (trx != null) {
@ -243,7 +244,7 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
type = schemaTypesEntry.type;
}
return type.decode(value).isRight();
return isRight(type.decode(value));
}
private async getSchema<T extends Schema.SchemaKey>(
@ -301,7 +302,7 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
}
const decoded = type.decode(value);
if (decoded.isLeft()) {
if (isLeft(decoded)) {
throw new TypeError(
`Cannot set value for ${key}, as value failed validation: ${inspect(
value,
@ -309,7 +310,7 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
)}`,
);
}
return decoded.value;
return decoded.right;
}) as ConfigMap<T>;
}
@ -355,10 +356,11 @@ export class Config extends (EventEmitter as new () => ConfigEventEmitter) {
decoded: Either<t.Errors, unknown>,
key: string,
value: unknown,
): void {
if (decoded.isLeft()) {
): decoded is Right<unknown> {
if (isLeft(decoded)) {
throw new ConfigurationValidationError(key, value);
}
return true;
}
}

View File

@ -1,3 +1,4 @@
import { either, isRight } from 'fp-ts/lib/Either';
import * as t from 'io-ts';
import * as _ from 'lodash';
@ -17,7 +18,7 @@ export const PermissiveBoolean = new t.Type<boolean, t.TypeOf<PermissiveType>>(
'PermissiveBoolean',
_.isBoolean,
(m, c) =>
permissiveValue.validate(m, c).chain(v => {
either.chain(permissiveValue.validate(m, c), v => {
switch (typeof v) {
case 'string':
case 'boolean':
@ -50,10 +51,7 @@ export const PermissiveNumber = new t.Type<number, string | number>(
'PermissiveNumber',
_.isNumber,
(m, c) =>
t
.union([t.string, t.number])
.validate(m, c)
.chain(v => {
either.chain(t.union([t.string, t.number]).validate(m, c), v => {
switch (typeof v) {
case 'number':
return t.success(v);
@ -80,14 +78,11 @@ export class StringJSON<T> extends t.Type<T, string> {
constructor(type: t.InterfaceType<any>) {
super(
'StringJSON',
(m): m is T => type.decode(m).isRight(),
(m): m is T => isRight(type.decode(m)),
(m, c) =>
// Accept either an object, or a string which represents the
// object
t
.union([t.string, type])
.validate(m, c)
.chain(v => {
either.chain(t.union([t.string, type]).validate(m, c), v => {
let obj: T;
if (typeof v === 'string') {
obj = JSON.parse(v);