New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

funtypes

Package Overview
Dependencies
Maintainers
2
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

funtypes - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

.size-snapshot.json

50

lib/asynccontract.d.ts

@@ -1,48 +0,10 @@

import { Runtype } from './index';
export interface AsyncContract0<Z> {
enforce(f: () => Promise<Z>): () => Promise<Z>;
import { RuntypeBase } from './runtype';
export interface AsyncContract<A extends any[], Z> {
enforce(f: (...a: A) => Promise<Z>): (...a: A) => Promise<Z>;
}
export interface AsyncContract1<A, Z> {
enforce(f: (a: A) => Promise<Z>): (a: A) => Promise<Z>;
}
export interface AsyncContract2<A, B, Z> {
enforce(f: (a: A, b: B) => Promise<Z>): (a: A, b: B) => Promise<Z>;
}
export interface AsyncContract3<A, B, C, Z> {
enforce(f: (a: A, b: B, c: C) => Promise<Z>): (a: A, b: B, c: C) => Promise<Z>;
}
export interface AsyncContract4<A, B, C, D, Z> {
enforce(f: (a: A, b: B, c: C, d: D) => Promise<Z>): (a: A, b: B, c: C, d: D) => Promise<Z>;
}
export interface AsyncContract5<A, B, C, D, E, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E) => Promise<Z>;
}
export interface AsyncContract6<A, B, C, D, E, F, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<Z>;
}
export interface AsyncContract7<A, B, C, D, E, F, G, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<Z>;
}
export interface AsyncContract8<A, B, C, D, E, F, G, H, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<Z>;
}
export interface AsyncContract9<A, B, C, D, E, F, G, H, I, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<Z>;
}
export interface AsyncContract10<A, B, C, D, E, F, G, H, I, J, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<Z>): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<Z>;
}
/**
* Create a function contract.
*/
export declare function AsyncContract<Z>(Z: Runtype<Z>): AsyncContract0<Z>;
export declare function AsyncContract<A, Z>(A: Runtype<A>, Z: Runtype<Z>): AsyncContract1<A, Z>;
export declare function AsyncContract<A, B, Z>(A: Runtype<A>, B: Runtype<B>, Z: Runtype<Z>): AsyncContract2<A, B, Z>;
export declare function AsyncContract<A, B, C, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, Z: Runtype<Z>): AsyncContract3<A, B, C, Z>;
export declare function AsyncContract<A, B, C, D, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, Z: Runtype<Z>): AsyncContract4<A, B, C, D, Z>;
export declare function AsyncContract<A, B, C, D, E, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, Z: Runtype<Z>): AsyncContract5<A, B, C, D, E, Z>;
export declare function AsyncContract<A, B, C, D, E, F, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, Z: Runtype<Z>): AsyncContract6<A, B, C, D, E, F, Z>;
export declare function AsyncContract<A, B, C, D, E, F, G, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, Z: Runtype<Z>): AsyncContract7<A, B, C, D, E, F, G, Z>;
export declare function AsyncContract<A, B, C, D, E, F, G, H, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, Z: Runtype<Z>): AsyncContract8<A, B, C, D, E, F, G, H, Z>;
export declare function AsyncContract<A, B, C, D, E, F, G, H, I, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, I: Runtype<I>, Z: Runtype<Z>): AsyncContract9<A, B, C, D, E, F, G, H, I, Z>;
export declare function AsyncContract<A, B, C, D, E, F, G, H, I, J, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, I: Runtype<I>, J: Runtype<J>, Z: Runtype<Z>): AsyncContract10<A, B, C, D, E, F, G, H, I, J, Z>;
export declare function AsyncContract<A extends [any, ...any[]] | [], Z>(argTypes: {
[key in keyof A]: key extends 'length' ? A['length'] : RuntypeBase<A[key]>;
}, returnType: RuntypeBase<Z>): AsyncContract<A, Z>;

@@ -1,48 +0,10 @@

import { Runtype } from './index';
export interface Contract0<Z> {
enforce(f: () => Z): () => Z;
import { RuntypeBase } from './runtype';
export interface Contract<A extends any[], Z> {
enforce(f: (...a: A) => Z): (...a: A) => Z;
}
export interface Contract1<A, Z> {
enforce(f: (a: A) => Z): (a: A) => Z;
}
export interface Contract2<A, B, Z> {
enforce(f: (a: A, b: B) => Z): (a: A, b: B) => Z;
}
export interface Contract3<A, B, C, Z> {
enforce(f: (a: A, b: B, c: C) => Z): (a: A, b: B, c: C) => Z;
}
export interface Contract4<A, B, C, D, Z> {
enforce(f: (a: A, b: B, c: C, d: D) => Z): (a: A, b: B, c: C, d: D) => Z;
}
export interface Contract5<A, B, C, D, E, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E) => Z): (a: A, b: B, c: C, d: D, e: E) => Z;
}
export interface Contract6<A, B, C, D, E, F, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F) => Z): (a: A, b: B, c: C, d: D, e: E, f: F) => Z;
}
export interface Contract7<A, B, C, D, E, F, G, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Z): (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Z;
}
export interface Contract8<A, B, C, D, E, F, G, H, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Z): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Z;
}
export interface Contract9<A, B, C, D, E, F, G, H, I, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Z): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Z;
}
export interface Contract10<A, B, C, D, E, F, G, H, I, J, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Z): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Z;
}
/**
* Create a function contract.
*/
export declare function Contract<Z>(Z: Runtype<Z>): Contract0<Z>;
export declare function Contract<A, Z>(A: Runtype<A>, Z: Runtype<Z>): Contract1<A, Z>;
export declare function Contract<A, B, Z>(A: Runtype<A>, B: Runtype<B>, Z: Runtype<Z>): Contract2<A, B, Z>;
export declare function Contract<A, B, C, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, Z: Runtype<Z>): Contract3<A, B, C, Z>;
export declare function Contract<A, B, C, D, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, Z: Runtype<Z>): Contract4<A, B, C, D, Z>;
export declare function Contract<A, B, C, D, E, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, Z: Runtype<Z>): Contract5<A, B, C, D, E, Z>;
export declare function Contract<A, B, C, D, E, F, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, Z: Runtype<Z>): Contract6<A, B, C, D, E, F, Z>;
export declare function Contract<A, B, C, D, E, F, G, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, Z: Runtype<Z>): Contract7<A, B, C, D, E, F, G, Z>;
export declare function Contract<A, B, C, D, E, F, G, H, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, Z: Runtype<Z>): Contract8<A, B, C, D, E, F, G, H, Z>;
export declare function Contract<A, B, C, D, E, F, G, H, I, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, I: Runtype<I>, Z: Runtype<Z>): Contract9<A, B, C, D, E, F, G, H, I, Z>;
export declare function Contract<A, B, C, D, E, F, G, H, I, J, Z>(A: Runtype<A>, B: Runtype<B>, C: Runtype<C>, D: Runtype<D>, E: Runtype<E>, F: Runtype<F>, G: Runtype<G>, H: Runtype<H>, I: Runtype<I>, J: Runtype<J>, Z: Runtype<Z>): Contract10<A, B, C, D, E, F, G, H, I, J, Z>;
export declare function Contract<A extends [any, ...any[]] | [], Z>(argTypes: {
[key in keyof A]: key extends 'length' ? A['length'] : RuntypeBase<A[key]>;
}, returnType: RuntypeBase<Z>): Contract<A, Z>;

@@ -0,0 +0,0 @@ export declare class ValidationError extends Error {

@@ -1,27 +0,32 @@

export { Runtype, Static } from './runtype';
export * from './reflect';
export * from './result';
export * from './contract';
export * from './asynccontract';
export * from './match';
export * from './errors';
export * from './types/unknown';
export * from './types/never';
export * from './types/void';
export { Literal, Undefined, Null } from './types/literal';
export * from './types/boolean';
export * from './types/number';
export * from './types/string';
export * from './types/symbol';
export * from './types/array';
export * from './types/tuple';
export * from './types/record';
export * from './types/dictionary';
export * from './types/union';
export * from './types/intersect';
export * from './types/function';
export { AsyncContract } from './asynccontract';
export { Contract } from './contract';
export { assertType } from './assertType';
export type { Runtype, Codec, Static } from './runtype';
export type { Success, Failure, Result } from './result';
export { ValidationError } from './errors';
export { Array, ReadonlyArray } from './types/array';
export { Boolean } from './types/boolean';
export type { ConstraintCheck } from './types/constraint';
export { Constraint, Guard } from './types/constraint';
export { Dictionary } from './types/dictionary';
export { Function } from './types/function';
export { InstanceOf } from './types/instanceof';
export * from './types/lazy';
export * from './types/constraint';
export { Intersect } from './types/intersect';
export { Lazy } from './types/lazy';
export type { LiteralValue } from './types/literal';
export { Literal, Null, Undefined } from './types/literal';
export { Never } from './types/never';
export { Number } from './types/number';
export { Object, Partial } from './types/Object';
export { Record } from './types/Record';
export { String } from './types/string';
export { Symbol } from './types/symbol';
export { Tuple } from './types/tuple';
export { Union } from './types/union';
export { Unknown } from './types/unknown';
/**
* @deprecated use Unknown
*/
export { Void } from './types/void';
export { Brand } from './types/brand';
export * from './decorator';
export { ParsedValue } from './types/ParsedValue';

@@ -1,34 +0,1122 @@

"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
class ValidationError extends Error {
constructor(message, key) {
super(key ? `${message} in ${key}` : message);
this.key = key;
this.name = 'ValidationError';
Object.setPrototypeOf(this, ValidationError.prototype);
}
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./contract"));
__export(require("./asynccontract"));
__export(require("./match"));
__export(require("./errors"));
__export(require("./types/unknown"));
__export(require("./types/never"));
__export(require("./types/void"));
var literal_1 = require("./types/literal");
exports.Literal = literal_1.Literal;
exports.Undefined = literal_1.Undefined;
exports.Null = literal_1.Null;
__export(require("./types/boolean"));
__export(require("./types/number"));
__export(require("./types/string"));
__export(require("./types/symbol"));
__export(require("./types/array"));
__export(require("./types/tuple"));
__export(require("./types/record"));
__export(require("./types/dictionary"));
__export(require("./types/union"));
__export(require("./types/intersect"));
__export(require("./types/function"));
var instanceof_1 = require("./types/instanceof");
exports.InstanceOf = instanceof_1.InstanceOf;
__export(require("./types/lazy"));
__export(require("./types/constraint"));
var brand_1 = require("./types/brand");
exports.Brand = brand_1.Brand;
__export(require("./decorator"));
function lazyValue(fn) {
let value;
return () => {
if (!value) {
value = fn();
}
return value;
};
}
function isLazyRuntype(runtype) {
return 'tag' in runtype && runtype.tag === 'lazy';
}
/**
* Construct a possibly-recursive Runtype.
*/
function Lazy(delayed) {
const underlying = lazyValue(delayed);
return create((value, _innerValidate, innerValidateToPlaceholder) => {
return innerValidateToPlaceholder(underlying(), value);
}, {
tag: 'lazy',
underlying,
show({ showChild, needsParens }) {
return showChild(underlying(), needsParens);
},
});
}
const show = (needsParens, circular) => (runtype) => {
const parenthesize = (s) => (needsParens ? `(${s})` : s);
const showChild = (runtype, needsParens) => show(needsParens, circular)(runtype);
if (circular.has(runtype)) {
if (isLazyRuntype(runtype)) {
const underlying = runtype.underlying();
if (underlying !== runtype) {
return show(needsParens, circular)(underlying);
}
}
return parenthesize(`CIRCULAR ${runtype.tag}`);
}
if (runtype.show) {
circular.add(runtype);
try {
return runtype.show({ parenthesize, showChild, needsParens });
}
finally {
circular.delete(runtype);
}
}
return runtype.tag;
};
var show$1 = show(false, new Set());
function isParsedValueRuntype(runtype) {
return 'tag' in runtype && runtype.tag === 'parsed';
}
function ParsedValue(underlying, config) {
return create({
validate: (value, _innerValidate, innerValidateToPlaceholder) => {
return mapValidationPlaceholder(innerValidateToPlaceholder(underlying, value), source => {
return config.parse(source);
}, config.test);
},
test(value, internalTest) {
if (config.test) {
return internalTest(config.test, value);
}
else {
return {
success: false,
message: `${config.name || `ParsedValue<${show$1(underlying)}>`} does not support Runtype.test`,
};
}
},
serialize(value, _internalSerialize, _internalSerializeToPlaceholder) {
if (!config.serialize) {
return {
success: false,
message: `${config.name || `ParsedValue<${show$1(underlying)}>`} does not support Runtype.serialize`,
};
}
const testResult = config.test
? innerGuard(config.test, value, createGuardVisitedState())
: undefined;
if (testResult) {
return testResult;
}
const serialized = config.serialize(value);
if (!serialized.success) {
return serialized;
}
return _internalSerializeToPlaceholder(underlying, serialized.value);
},
}, {
tag: 'parsed',
underlying,
config,
show({ showChild }) {
return config.name || `ParsedValue<${showChild(underlying, false)}>`;
},
});
}
const internal = '__internal__';
function create(internalImplementation, config) {
const A = {
...config,
assert,
parse,
check: parse,
safeParse,
validate: safeParse,
test,
guard: test,
serialize,
safeSerialize,
Or,
And,
withConstraint,
withGuard,
withBrand,
withParser,
toString: () => `Runtype<${show$1(A)}>`,
[internal]: typeof internalImplementation === 'function'
? {
validate: internalImplementation,
}
: internalImplementation,
};
return A;
function safeParse(x) {
return innerValidate(A, x, createVisitedState());
}
function safeSerialize(x) {
return innerSerialize(A, x, createVisitedState());
}
function parse(x) {
const validated = safeParse(x);
if (!validated.success) {
throw new ValidationError(validated.message, validated.key);
}
return validated.value;
}
function serialize(x) {
const validated = safeSerialize(x);
if (!validated.success) {
throw new ValidationError(validated.message, validated.key);
}
return validated.value;
}
function assert(x) {
const validated = innerGuard(A, x, createGuardVisitedState());
if (validated) {
throw new ValidationError(validated.message, validated.key);
}
}
function test(x) {
const validated = innerGuard(A, x, createGuardVisitedState());
return validated === undefined;
}
function Or(B) {
return Union(A, B);
}
function And(B) {
return Intersect(A, B);
}
function withConstraint(constraint, options) {
return Constraint(A, constraint, options);
}
function withGuard(test, options) {
return Constraint(A, test, options);
}
function withBrand(B) {
return Brand(B, A);
}
function withParser(config) {
return ParsedValue(A, config);
}
}
function attemptMixin(placeholder, value) {
if (placeholder === value) {
return { success: true, value };
}
if (Array.isArray(placeholder) && Array.isArray(value)) {
placeholder.splice(0, placeholder.length, ...value);
return { success: true, value: placeholder };
}
if (placeholder &&
typeof placeholder === 'object' &&
!Array.isArray(placeholder) &&
value &&
typeof value === 'object' &&
!Array.isArray(value)) {
Object.assign(placeholder, value);
return { success: true, value: placeholder };
}
return {
success: false,
message: `Cannot convert a value of type "${Array.isArray(placeholder) ? 'Array' : typeof placeholder}" into a value of type "${value === null ? 'null' : Array.isArray(value) ? 'Array' : typeof value}" when it contains cycles.`,
};
}
function createValidationPlaceholder(placeholder, fn) {
return innerMapValidationPlaceholder(placeholder, () => fn(placeholder) || { success: true, value: placeholder });
}
function mapValidationPlaceholder(source, fn, extraGuard) {
if (!source.success)
return source;
if (!source.cycle) {
const result = fn(source.value);
return ((result.success &&
extraGuard &&
innerGuard(extraGuard, result.value, createGuardVisitedState())) ||
result);
}
return innerMapValidationPlaceholder(Array.isArray(source.placeholder) ? [...source.placeholder] : { ...source.placeholder }, () => source.unwrap(), fn, extraGuard);
}
function innerMapValidationPlaceholder(placeholder, populate, fn, extraGuard) {
let hasCycle = false;
let cache;
const cycle = {
success: true,
cycle: true,
placeholder,
unwrap: () => {
if (cache) {
hasCycle = true;
return cache;
}
cache = { success: true, value: placeholder };
const sourceResult = populate();
const result = sourceResult.success && fn ? fn(sourceResult.value) : sourceResult;
if (!result.success)
return result;
if (hasCycle) {
const unwrapResult = attemptMixin(cache.value, result.value);
const guardFailure = unwrapResult.success &&
extraGuard &&
innerGuard(extraGuard, unwrapResult.value, createGuardVisitedState());
cache = guardFailure || unwrapResult;
}
else {
const guardFailure = extraGuard && innerGuard(extraGuard, result.value, createGuardVisitedState());
cache = guardFailure || result;
}
if (cache.success) {
cycle.placeholder = cache.value;
}
return cache;
},
};
return cycle;
}
function unwrapVisitedState(o) {
return o;
}
function wrapVisitedState(o) {
return o;
}
function createVisitedState() {
return wrapVisitedState(new Map());
}
function unwrapGuardVisitedState(o) {
return o;
}
function wrapGuardVisitedState(o) {
return o;
}
function createGuardVisitedState() {
return wrapGuardVisitedState(new Map());
}
function innerValidate(targetType, value, $visited) {
const result = innerValidateToPlaceholder(targetType, value, $visited);
if (result.cycle) {
return result.unwrap();
}
return result;
}
function innerValidateToPlaceholder(targetType, value, $visited) {
var _a;
const visited = unwrapVisitedState($visited);
const validator = targetType[internal];
const cached = (_a = visited.get(targetType)) === null || _a === void 0 ? void 0 : _a.get(value);
if (cached !== undefined) {
return cached;
}
const result = validator.validate(value, (t, v) => innerValidate(t, v, $visited), (t, v) => innerValidateToPlaceholder(t, v, $visited));
if (result.cycle) {
visited.set(targetType, (visited.get(targetType) || new Map()).set(value, result));
return result;
}
return result;
}
function innerSerialize(targetType, value, $visited) {
const result = innerSerializeToPlaceholder(targetType, value, $visited);
if (result.cycle) {
return result.unwrap();
}
return result;
}
function innerSerializeToPlaceholder(targetType, value, $visited) {
var _a;
const visited = unwrapVisitedState($visited);
const validator = targetType[internal];
const cached = (_a = visited.get(targetType)) === null || _a === void 0 ? void 0 : _a.get(value);
if (cached !== undefined) {
return cached;
}
let result = (validator.serialize || validator.validate)(value, (t, v) => innerSerialize(t, v, $visited), (t, v) => innerSerializeToPlaceholder(t, v, $visited));
if (result.cycle) {
visited.set(targetType, (visited.get(targetType) || new Map()).set(value, result));
return result;
}
return result;
}
function innerGuard(targetType, value, $visited) {
var _a;
const visited = unwrapGuardVisitedState($visited);
const validator = targetType[internal];
if (value && (typeof value === 'object' || typeof value === 'function')) {
const cached = (_a = visited.get(targetType)) === null || _a === void 0 ? void 0 : _a.has(value);
if (cached)
return undefined;
visited.set(targetType, (visited.get(targetType) || new Set()).add(value));
}
if (validator.test) {
return validator.test(value, (t, v) => innerGuard(t, v, $visited));
}
let result = validator.validate(value, (t, v) => innerGuard(t, v, $visited) || { success: true, value: v }, (t, v) => innerGuard(t, v, $visited) || { success: true, value: v });
if (result.cycle)
result = result.unwrap();
if (result.success)
return undefined;
else
return result;
}
/**
* Create a function contract.
*/
function AsyncContract(argTypes, returnType) {
return {
enforce: (f) => (...args) => {
if (args.length < argTypes.length) {
return Promise.reject(new ValidationError(`Expected ${argTypes.length} arguments but only received ${args.length}`));
}
const visited = createVisitedState();
for (let i = 0; i < argTypes.length; i++) {
const result = innerValidate(argTypes[i], args[i], visited);
if (result.success) {
args[i] = result.value;
}
else {
return Promise.reject(new ValidationError(result.message, result.key));
}
}
const returnedPromise = f(...args);
if (!(returnedPromise instanceof Promise)) {
return Promise.reject(new ValidationError(`Expected function to return a promise, but instead got ${returnedPromise}`));
}
return returnedPromise.then(value => {
const result = innerGuard(returnType, value, createGuardVisitedState());
if (result) {
throw new ValidationError(result.message, result.key);
}
return value;
});
},
};
}
/**
* Create a function contract.
*/
function Contract(argTypes, returnType) {
return {
enforce: (f) => (...args) => {
if (args.length < argTypes.length)
throw new ValidationError(`Expected ${argTypes.length} arguments but only received ${args.length}`);
const visited = createVisitedState();
for (let i = 0; i < argTypes.length; i++) {
const result = innerValidate(argTypes[i], args[i], visited);
if (result.success) {
args[i] = result.value;
}
else {
throw new ValidationError(result.message, result.key);
}
}
const rawResult = f(...args);
const result = innerGuard(returnType, rawResult, createGuardVisitedState());
if (result) {
throw new ValidationError(result.message, result.key);
}
return rawResult;
},
};
}
function assertType(rt, v) {
rt.assert(v);
}
/**
* Construct an array runtype from a runtype for its elements.
*/
function InternalArr(element, isReadonly) {
const result = create((xs, innerValidate) => {
if (!Array.isArray(xs)) {
return {
success: false,
message: `Expected array, but was ${xs === null ? xs : typeof xs}`,
};
}
return createValidationPlaceholder([...xs], placeholder => {
for (let i = 0; i < xs.length; i++) {
const validated = innerValidate(element, xs[i]);
if (!validated.success) {
return {
success: false,
message: validated.message,
key: validated.key ? `[${i}].${validated.key}` : `[${i}]`,
};
}
else {
placeholder[i] = validated.value;
}
}
});
}, {
tag: 'array',
isReadonly,
element,
show({ showChild }) {
return `${isReadonly ? 'readonly ' : ''}${showChild(element, true)}[]`;
},
});
if (!isReadonly) {
result.asReadonly = asReadonly;
}
return result;
function asReadonly() {
return InternalArr(element, true);
}
}
function Arr(element) {
return InternalArr(element, false);
}
function ReadonlyArray(element) {
return InternalArr(element, true);
}
/**
* Validates that a value is a boolean.
*/
const Boolean = create(value => typeof value === 'boolean'
? { success: true, value }
: {
success: false,
message: `Expected boolean, but was ${value === null ? value : typeof value}`,
}, { tag: 'boolean' });
/**
* Validates that a value is a string.
*/
const String$1 = create(value => typeof value === 'string'
? { success: true, value }
: {
success: false,
message: `Expected string, but was ${value === null ? value : typeof value}`,
}, { tag: 'string' });
/**
* Validates anything, but provides no new type information about it.
*/
const Unknown = create(value => ({ success: true, value }), {
tag: 'unknown',
});
function isConstraintRuntype(runtype) {
return ('tag' in runtype && runtype.tag === 'constraint');
}
function Constraint(underlying, constraint, options) {
return create((value, innerValidate) => {
const name = options && options.name;
const validated = innerValidate(underlying, value);
if (!validated.success) {
return validated;
}
const result = constraint(validated.value);
if (String$1.test(result))
return { success: false, message: result };
else if (!result)
return { success: false, message: `Failed ${name || 'constraint'} check` };
return { success: true, value: validated.value };
}, {
tag: 'constraint',
underlying,
constraint,
name: options && options.name,
args: options && options.args,
show({ needsParens, showChild }) {
return (options && options.name) || showChild(underlying, needsParens);
},
});
}
const Guard = (test, options) => Unknown.withGuard(test, options);
function Dictionary(value, key = 'string') {
return Record(key === 'number' ? Number : String$1, value);
}
/**
* Construct a runtype for functions.
*/
const Function = create(value => typeof value === 'function'
? { success: true, value }
: {
success: false,
message: `Expected function, but was ${value === null ? value : typeof value}`,
}, { tag: 'function' });
function InstanceOf(ctor) {
return create(value => value instanceof ctor
? { success: true, value }
: {
success: false,
message: `Expected ${ctor.name}, but was ${value === null ? value : typeof value}`,
}, {
tag: 'instanceof',
ctor: ctor,
show() {
const name = ctor.name;
return `InstanceOf<${name}>`;
},
});
}
/**
* Construct an intersection runtype from runtypes for its alternatives.
*/
function Intersect(...intersectees) {
return create((value, innerValidate) => {
if (Array.isArray(value)) {
return createValidationPlaceholder([...value], placeholder => {
for (const targetType of intersectees) {
let validated = innerValidate(targetType, placeholder);
if (!validated.success) {
return validated;
}
if (!Array.isArray(validated.value)) {
return {
success: false,
message: `The validator ${show$1(targetType)} attempted to convert the type of this value from an array to something else. That conversion is not valid as the child of an intersect`,
};
}
placeholder.splice(0, placeholder.length, ...validated.value);
}
});
}
else if (value && typeof value === 'object') {
return createValidationPlaceholder({}, placeholder => {
for (const targetType of intersectees) {
let validated = innerValidate(targetType, value);
if (!validated.success) {
return validated;
}
if (!(validated.value && typeof validated.value === 'object')) {
return {
success: false,
message: `The validator ${show$1(targetType)} attempted to convert the type of this value from an object to something else. That conversion is not valid as the child of an intersect`,
};
}
Object.assign(placeholder, validated.value);
}
});
}
let result = value;
for (const targetType of intersectees) {
let validated = innerValidate(targetType, result);
if (!validated.success) {
return validated;
}
result = validated.value;
}
return { success: true, value: result };
}, {
tag: 'intersect',
intersectees,
show({ parenthesize, showChild }) {
return parenthesize(`${intersectees.map(v => showChild(v, true)).join(' & ')}`);
},
});
}
/**
* Be aware of an Array of Symbols `[Symbol()]` which would throw "TypeError: Cannot convert a Symbol value to a string"
*/
function literal(value) {
return Array.isArray(value) ? String(value.map(String)) : String(value);
}
function isLiteralRuntype(runtype) {
return 'tag' in runtype && runtype.tag === 'literal';
}
/**
* Construct a runtype for a type literal.
*/
function Literal(valueBase) {
return create(value => value === valueBase
? { success: true, value }
: {
success: false,
message: `Expected literal '${literal(valueBase)}', but was '${literal(value)}'`,
}, {
tag: 'literal',
value: valueBase,
show() {
return typeof valueBase === 'string' ? `"${valueBase}"` : String(valueBase);
},
});
}
/**
* An alias for Literal(undefined).
*/
const Undefined = Literal(undefined);
/**
* An alias for Literal(null).
*/
const Null = Literal(null);
/**
* Validates nothing (unknown fails).
*/
const Never = create(value => ({
success: false,
message: `Expected nothing, but was ${value === null ? value : typeof value}`,
}), { tag: 'never' });
/**
* Validates that a value is a number.
*/
const Number = create(value => typeof value === 'number'
? { success: true, value }
: {
success: false,
message: `Expected number, but was ${value === null ? value : typeof value}`,
}, { tag: 'number' });
// Type test to determine if an object has a given key
// If this feature gets implemented, we can use `in` instead: https://github.com/Microsoft/TypeScript/issues/10485
function hasKey(k, o) {
return typeof o === 'object' && k in o;
}
function isObjectRuntype(runtype) {
return ('tag' in runtype && runtype.tag === 'object');
}
/**
* Construct an object runtype from runtypes for its values.
*/
function InternalObject(fields, isPartial, isReadonly) {
const runtype = create((x, innerValidate) => {
if (x === null || x === undefined) {
return { success: false, message: `Expected ${show$1(runtype)}, but was ${x}` };
}
if (typeof x !== 'object') {
return { success: false, message: `Expected ${show$1(runtype)}, but was ${typeof x}` };
}
if (Array.isArray(x)) {
return { success: false, message: `Expected ${show$1(runtype)}, but was an Array` };
}
return createValidationPlaceholder({}, (placeholder) => {
for (const key in fields) {
if (!isPartial || (hasKey(key, x) && x[key] !== undefined)) {
const value = isPartial || hasKey(key, x) ? x[key] : undefined;
let validated = innerValidate(fields[key], value);
if (!validated.success) {
return {
success: false,
message: validated.message,
key: validated.key ? `${key}.${validated.key}` : key,
};
}
placeholder[key] = validated.value;
}
}
});
}, {
tag: 'object',
isPartial,
isReadonly,
fields,
asPartial,
asReadonly,
pick,
omit,
show({ showChild }) {
const keys = Object.keys(fields);
return keys.length
? `{ ${keys
.map(k => `${isReadonly ? 'readonly ' : ''}${k}${isPartial ? '?' : ''}: ${showChild(fields[k], false)};`)
.join(' ')} }`
: '{}';
},
});
return runtype;
function asPartial() {
return InternalObject(runtype.fields, true, runtype.isReadonly);
}
function asReadonly() {
return InternalObject(runtype.fields, runtype.isPartial, true);
}
function pick(...keys) {
const newFields = {};
for (const key of keys) {
newFields[key] = fields[key];
}
return InternalObject(newFields, isPartial, isReadonly);
}
function omit(...keys) {
const newFields = { ...fields };
for (const key of keys) {
if (key in newFields)
delete newFields[key];
}
return InternalObject(newFields, isPartial, isReadonly);
}
}
function Obj(fields) {
return InternalObject(fields, false, false);
}
function Partial(fields) {
return InternalObject(fields, true, false);
}
function getExpectedBaseType(key) {
switch (key.tag) {
case 'string':
return 'string';
case 'number':
return 'number';
case 'literal':
return typeof key.value;
case 'union':
const baseTypes = key.alternatives.map(getExpectedBaseType);
return baseTypes.reduce((a, b) => (a === b ? a : 'mixed'), baseTypes[0]);
case 'constraint':
return getExpectedBaseType(key.underlying);
}
}
function Record(...args) {
if (args.length === 1 && args[0] && typeof args[0] === 'object') {
return Obj(args[0]);
}
return RecordInternal(args[0], args[1]);
}
function RecordInternal(key, value) {
const expectedBaseType = lazyValue(() => getExpectedBaseType(key));
const runtype = create((x, innerValidate) => {
if (x === null || x === undefined) {
return { success: false, message: `Expected ${show$1(runtype)}, but was ${x}` };
}
if (typeof x !== 'object') {
return { success: false, message: `Expected ${show$1(runtype)}, but was ${typeof x}` };
}
if (Object.getPrototypeOf(x) !== Object.prototype) {
if (!Array.isArray(x)) {
return {
success: false,
message: `Expected ${show$1(runtype)}, but was ${Object.getPrototypeOf(x)}`,
};
}
return { success: false, message: 'Expected record, but was array' };
}
return createValidationPlaceholder({}, placeholder => {
for (const k in x) {
let keyValidation = null;
if (expectedBaseType() === 'number') {
if (isNaN(+k))
return {
success: false,
message: `Expected record key to be a number, but was '${k}'`,
};
keyValidation = innerValidate(key, +k);
}
else if (expectedBaseType() === 'string') {
keyValidation = innerValidate(key, k);
}
else {
keyValidation = innerValidate(key, k);
if (!keyValidation.success && !isNaN(+k)) {
keyValidation = innerValidate(key, +k);
}
}
if (!keyValidation.success) {
return {
success: false,
message: `Expected record key to be ${show$1(key)}, but was '${k}'`,
};
}
const validated = innerValidate(value, x[k]);
if (!validated.success) {
return {
success: false,
message: validated.message,
key: validated.key ? `${k}.${validated.key}` : k,
};
}
placeholder[keyValidation.value] = validated.value;
}
});
}, {
tag: 'record',
key,
value,
show({ showChild }) {
return `{ [_: ${showChild(key, false)}]: ${showChild(value, false)} }`;
},
});
return runtype;
}
/**
* Validates that a value is a symbol.
*/
const Sym = create(value => typeof value === 'symbol'
? { success: true, value }
: {
success: false,
message: `Expected symbol, but was ${value === null ? value : typeof value}`,
}, { tag: 'symbol' });
function isTupleRuntype(runtype) {
return 'tag' in runtype && runtype.tag === 'tuple';
}
/**
* Construct a tuple runtype from runtypes for each of its elements.
*/
function Tuple(...components) {
return create((x, innerValidate) => {
const validated = innerValidate(Arr(Unknown), x);
if (!validated.success) {
return {
success: false,
message: `Expected tuple to be an array: ${validated.message}`,
key: validated.key,
};
}
if (validated.value.length !== components.length) {
return {
success: false,
message: `Expected an array of length ${components.length}, but was ${validated.value.length}`,
};
}
return createValidationPlaceholder(validated.value, placeholder => {
for (let i = 0; i < components.length; i++) {
let validatedComponent = innerValidate(components[i], validated.value[i]);
if (!validatedComponent.success) {
return {
success: false,
message: validatedComponent.message,
key: validatedComponent.key ? `[${i}].${validatedComponent.key}` : `[${i}]`,
};
}
placeholder[i] = validatedComponent.value;
}
});
}, {
tag: 'tuple',
components,
show({ showChild }) {
return `[${components
.map(e => showChild(e, false))
.join(', ')}]`;
},
});
}
function isBrandRuntype(runtype) {
return 'tag' in runtype && runtype.tag === 'brand';
}
function Brand(brand, entity) {
return create((value, _innerValidate, innerValidateToPlaceholder) => {
return innerValidateToPlaceholder(entity, value);
}, {
tag: 'brand',
brand,
entity,
show({ showChild, needsParens }) {
return showChild(entity, needsParens);
},
});
}
function valueToString(value) {
return value === null || typeof value === 'number' || typeof value === 'boolean'
? value
: typeof value === 'string'
? `'${value}'`
: typeof value;
}
function resolveUnderlyingType(runtype, mode) {
if (isLazyRuntype(runtype))
return resolveUnderlyingType(runtype.underlying(), mode);
if (isBrandRuntype(runtype))
return resolveUnderlyingType(runtype.entity, mode);
if (isConstraintRuntype(runtype))
return resolveUnderlyingType(runtype.underlying, mode);
if (mode === 'p' && isParsedValueRuntype(runtype))
return resolveUnderlyingType(runtype.underlying, mode);
if (mode === 't' && isParsedValueRuntype(runtype)) {
return runtype.config.test ? resolveUnderlyingType(runtype.config.test, mode) : Never;
}
if (mode === 's' && isParsedValueRuntype(runtype)) {
if (!runtype.config.serialize) {
// this node can never match
return Never;
}
return runtype.config.test ? resolveUnderlyingType(runtype.config.test, mode) : runtype;
}
return runtype;
}
/**
* Construct a union runtype from runtypes for its alternatives.
*/
function Union(...alternatives) {
function validateWithKey(tag, types) {
return (value, innerValidate) => {
if (!value || typeof value !== 'object') {
return {
success: false,
message: `Expected ${show$1(runtype)}, but was ${value === null ? value : typeof value}`,
};
}
const validator = types.get(value[tag]);
if (validator) {
const result = innerValidate(validator, value);
if (!result.success) {
return {
success: false,
message: result.message,
key: `<${tag === 0 ? `[0]` : tag}: ${valueToString(value[tag])}>${result.key ? `.${result.key}` : ``}`,
};
}
return result;
}
else {
return {
success: false,
message: `Expected ${Array.from(types.keys())
.map(v => (typeof v === 'string' ? `'${v}'` : v))
.join(' | ')}, but was ${valueToString(value[tag])}`,
key: tag === 0 ? `[0]` : tag,
};
}
};
}
// This must be lazy to avoid eagerly evaluating any circular references
const validatorOf = (mode) => {
const excludingNever = alternatives.filter(t => resolveUnderlyingType(t, mode).tag !== 'never');
if (excludingNever.length) {
const alts = excludingNever.map(t => resolveUnderlyingType(t, mode));
const recordAlternatives = alts.filter(isObjectRuntype);
if (recordAlternatives.length === excludingNever.length) {
const commonLiteralFields = {};
for (let i = 0; i < excludingNever.length; i++) {
for (const fieldName in recordAlternatives[i].fields) {
const field = resolveUnderlyingType(recordAlternatives[i].fields[fieldName], mode);
if (isLiteralRuntype(field)) {
if (!commonLiteralFields[fieldName]) {
commonLiteralFields[fieldName] = new Map();
}
if (!commonLiteralFields[fieldName].has(field.value)) {
commonLiteralFields[fieldName].set(field.value,
// @ts-expect-error
excludingNever[i]);
}
}
}
}
for (const tag of ['type', 'kind', 'tag', ...Object.keys(commonLiteralFields)]) {
if (tag in commonLiteralFields &&
commonLiteralFields[tag].size === excludingNever.length) {
return validateWithKey(tag, commonLiteralFields[tag]);
}
}
}
const tupleAlternatives = alts.filter(isTupleRuntype);
if (tupleAlternatives.length === excludingNever.length) {
const commonLiteralFields = new Map();
for (let i = 0; i < excludingNever.length; i++) {
const field = resolveUnderlyingType(tupleAlternatives[i].components[0], mode);
if (isLiteralRuntype(field)) {
if (!commonLiteralFields.has(field.value)) {
commonLiteralFields.set(field.value,
// @ts-expect-error
excludingNever[i]);
}
}
}
if (commonLiteralFields.size === excludingNever.length) {
return validateWithKey(0, commonLiteralFields);
}
}
}
return (value, innerValidate) => {
let errorsWithKey = 0;
let lastError;
let lastErrorRuntype;
for (const targetType of alternatives) {
const result = innerValidate(targetType, value);
if (result.success) {
return result;
}
if (result.key) {
errorsWithKey++;
lastError = result;
lastErrorRuntype = targetType;
}
}
if (lastError && lastErrorRuntype && errorsWithKey === 1) {
return {
success: false,
message: lastError.message,
key: `<${show$1(lastErrorRuntype)}>.${lastError.key}`,
};
}
return {
success: false,
message: `Expected ${show$1(runtype)}, but was ${value === null ? value : typeof value}`,
};
};
};
const innerValidator = lazyValue(() => ({
p: validatorOf('p'),
s: validatorOf('s'),
t: validatorOf('t'),
}));
const runtype = create({
validate: (value, visited) => {
return innerValidator().p(value, visited);
},
serialize: (value, visited) => {
return innerValidator().s(value, visited);
},
test: (value, visited) => {
const result = innerValidator().s(value, (t, v) => visited(t, v) || { success: true, value: v });
return result.success ? undefined : result;
},
}, {
tag: 'union',
alternatives,
match: match,
show({ parenthesize, showChild }) {
return parenthesize(`${alternatives.map(v => showChild(v, true)).join(' | ')}`);
},
});
return runtype;
function match(...cases) {
return (x) => {
const visited = createVisitedState();
for (let i = 0; i < alternatives.length; i++) {
const input = innerValidate(alternatives[i], x, visited);
if (input.success) {
return cases[i](input.value);
}
}
// if none of the types matched, we should fail with an assertion error
runtype.assert(x);
};
}
}
/**
* Void is an alias for Unknown
*
* @deprecated Please use Unknown instead
*/
const Void = Unknown;
exports.Array = Arr;
exports.AsyncContract = AsyncContract;
exports.Boolean = Boolean;
exports.Brand = Brand;
exports.Constraint = Constraint;
exports.Contract = Contract;
exports.Dictionary = Dictionary;
exports.Function = Function;
exports.Guard = Guard;
exports.InstanceOf = InstanceOf;
exports.Intersect = Intersect;
exports.Lazy = Lazy;
exports.Literal = Literal;
exports.Never = Never;
exports.Null = Null;
exports.Number = Number;
exports.Object = Obj;
exports.ParsedValue = ParsedValue;
exports.Partial = Partial;
exports.ReadonlyArray = ReadonlyArray;
exports.Record = Record;
exports.String = String$1;
exports.Symbol = Sym;
exports.Tuple = Tuple;
exports.Undefined = Undefined;
exports.Union = Union;
exports.Unknown = Unknown;
exports.ValidationError = ValidationError;
exports.Void = Void;
exports.assertType = assertType;

@@ -0,0 +0,0 @@ /**

@@ -1,34 +0,79 @@

import { Result, Union2, Intersect2, Constraint, ConstraintCheck, Brand } from './index';
import { Reflect } from './reflect';
import { Result, Union, Intersect, Constraint, ConstraintCheck, Brand, Failure } from './index';
import { ParsedValue, ParsedValueConfig } from './types/ParsedValue';
export declare type InnerValidateHelper = <T>(runtype: RuntypeBase<T>, value: unknown) => Result<T>;
declare const internalSymbol: unique symbol;
declare const internal: typeof internalSymbol;
export declare type ResultWithCycle<T> = (Result<T> & {
cycle?: false;
}) | Cycle<T>;
export interface InternalValidation<TParsed> {
validate(x: any, innerValidate: <T>(runtype: RuntypeBase<T>, value: unknown) => Result<T>, innerValidateToPlaceholder: <T>(runtype: RuntypeBase<T>, value: unknown) => ResultWithCycle<T>): ResultWithCycle<TParsed>;
test?: (x: any, innerValidate: <T>(runtype: RuntypeBase<T>, value: unknown) => Failure | undefined) => Failure | undefined;
serialize?: (x: any, innerSerialize: (runtype: RuntypeBase, value: unknown) => Result<any>, innerSerializeToPlaceholder: (runtype: RuntypeBase, value: unknown) => ResultWithCycle<any>) => ResultWithCycle<any>;
}
/**
* A runtype determines at runtime whether a value conforms to a type specification.
*/
export interface Runtype<A = unknown> {
export interface RuntypeBase<TParsed = unknown> {
readonly tag: string;
/**
* Verifies that a value conforms to this runtype. When given a value that does
* not conform to the runtype, throws an exception.
*
* @throws ValidationError
*/
assert(x: any): asserts x is A;
assert(x: any): asserts x is TParsed;
/**
* Verifies that a value conforms to this runtype. If so, returns the same value,
* statically typed. Otherwise throws an exception.
* A type guard for this runtype.
*/
check(x: any): A;
test(x: any): x is TParsed;
/**
* Validates that a value conforms to this type, and returns a result indicating
* success or failure (does not throw).
* @deprecated use Runtype.test
*/
validate(x: any): Result<A>;
guard(x: any): x is TParsed;
/**
* A type guard for this runtype.
* Validates the value conforms to this type, and performs
* the `parse` action for any `ParsedValue` types.
*
* If the value is valid, it returns the parsed value,
* otherwise it throws a ValidationError.
*
* @throws ValidationError
*/
guard(x: any): x is A;
parse(x: any): TParsed;
/**
* @deprecated use Runtype.parse
*/
check(x: any): TParsed;
/**
* Validates the value conforms to this type, and performs
* the `parse` action for any `ParsedValue` types.
*
* Returns a `Result`, constaining the parsed value or
* error message. Does not throw!
*/
safeParse(x: any): Result<TParsed>;
/**
* @deprecated use Runtype.safeParse
*/
validate(x: any): Result<TParsed>;
show?: (ctx: {
needsParens: boolean;
parenthesize: (str: string) => string;
showChild: (rt: RuntypeBase, needsParens: boolean) => string;
}) => string;
[internal]: InternalValidation<TParsed>;
}
/**
* A runtype determines at runtime whether a value conforms to a type specification.
*/
export interface Runtype<TParsed> extends RuntypeBase<TParsed> {
/**
* Union this Runtype with another.
*/
Or<B extends Runtype>(B: B): Union2<this, B>;
Or<B extends RuntypeBase>(B: B): Union<[this, B]>;
/**
* Intersect this Runtype with another.
*/
And<B extends Runtype>(B: B): Intersect2<this, B>;
And<B extends RuntypeBase>(B: B): Intersect<[this, B]>;
/**

@@ -54,7 +99,7 @@ * Use an arbitrary constraint function to validate a runtype, and optionally

* via a type guard function. The static type of the runtype is inferred from
* the type of the guard function.
* the type of the test function.
*
* @template T - Typically inferred from the return type of the type guard
* function, so usually not needed to specify manually.
* @param {(x: Static<this>) => x is T} guard - Type guard function (see
* @param {(x: Static<this>) => x is T} test - Type test function (see
* https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)

@@ -67,3 +112,3 @@ *

*/
withGuard<T extends Static<this>, K = unknown>(guard: (x: Static<this>) => x is T, options?: {
withGuard<T extends Static<this>, K = unknown>(test: (x: Static<this>) => x is T, options?: {
name?: string;

@@ -77,17 +122,49 @@ args?: K;

/**
* Convert this to a Reflect, capable of introspecting the structure of the type.
* Apply conversion functions when parsing/serializing this value
*/
reflect: Reflect;
_falseWitness: A;
withParser<TParsed>(value: ParsedValueConfig<this, TParsed>): ParsedValue<this, TParsed>;
}
export interface Codec<TParsed> extends Runtype<TParsed> {
/**
* Validates the value conforms to this type, and performs
* the `serialize` action for any `ParsedValue` types.
*
* If the value is valid, and the type supports serialize,
* it returns the serialized value, otherwise it throws a
* ValidationError.
*
* @throws ValidationError
*/
serialize: (x: TParsed) => unknown;
/**
* Validates the value conforms to this type, and performs
* the `serialize` action for any `ParsedValue` types.
*
* Returns a `Result`, constaining the serialized value or
* error message. Does not throw!
*/
safeSerialize: (x: TParsed) => Result<unknown>;
}
/**
* Obtains the static type associated with a Runtype.
*/
export declare type Static<A extends Runtype> = A['_falseWitness'];
export declare function create<A extends Runtype>(validate: (x: any, visited: VisitedState) => Result<Static<A>>, A: any): A;
export declare function innerValidate<A extends Runtype>(targetType: A, value: any, visited: VisitedState): Result<Static<A>>;
declare type VisitedState = {
has: (candidate: object, type: Runtype) => boolean;
export declare type Static<A extends RuntypeBase<any>> = A extends RuntypeBase<infer T> ? T : unknown;
export declare function create<TConfig extends Codec<any>>(internalImplementation: InternalValidation<Static<TConfig>> | InternalValidation<Static<TConfig>>['validate'], config: Omit<TConfig, 'assert' | 'check' | 'test' | 'guard' | 'parse' | 'check' | 'safeParse' | 'validate' | 'serialize' | 'safeSerialize' | 'Or' | 'And' | 'withConstraint' | 'withGuard' | 'withBrand' | 'withParser' | typeof internal>): TConfig;
export declare type Cycle<T> = {
success: true;
cycle: true;
placeholder: Partial<T>;
unwrap: () => Result<T>;
};
declare function VisitedState(): VisitedState;
export declare function createValidationPlaceholder<T>(placeholder: T, fn: (placeholder: T) => Failure | undefined): Cycle<T>;
export declare function mapValidationPlaceholder<T, S>(source: ResultWithCycle<T>, fn: (placeholder: T) => Result<S>, extraGuard?: RuntypeBase<S>): ResultWithCycle<S>;
declare const OpaqueVisitedState: unique symbol;
export declare type OpaqueVisitedState = typeof OpaqueVisitedState;
export declare function createVisitedState(): OpaqueVisitedState;
declare const OpaqueGuardVisitedState: unique symbol;
export declare type OpaqueGuardVisitedState = typeof OpaqueGuardVisitedState;
export declare function createGuardVisitedState(): OpaqueGuardVisitedState;
export declare function innerValidate<T>(targetType: RuntypeBase<T>, value: any, $visited: OpaqueVisitedState): Result<T>;
export declare function innerSerialize<T>(targetType: RuntypeBase<T>, value: any, $visited: OpaqueVisitedState): Result<T>;
export declare function innerGuard(targetType: RuntypeBase, value: any, $visited: OpaqueGuardVisitedState): Failure | undefined;
export {};

@@ -1,3 +0,3 @@

import { Reflect } from './index';
declare const _default: (refl: Reflect) => string;
import { RuntypeBase } from './runtype';
declare const _default: (runtype: RuntypeBase<unknown>) => string;
export default _default;

@@ -1,10 +0,15 @@

import { Runtype, Static } from '../runtype';
declare type ArrayStaticType<E extends Runtype, RO extends boolean> = RO extends true ? ReadonlyArray<Static<E>> : Static<E>[];
interface Arr<E extends Runtype, RO extends boolean> extends Runtype<ArrayStaticType<E, RO>> {
tag: 'array';
element: E;
isReadonly: RO;
asReadonly(): Arr<E, true>;
import { Static, RuntypeBase, Codec } from '../runtype';
export interface ReadonlyArray<E extends RuntypeBase<unknown> = RuntypeBase<unknown>> extends Codec<readonly Static<E>[]> {
readonly tag: 'array';
readonly element: E;
readonly isReadonly: true;
}
declare function Arr<E extends Runtype, RO extends boolean>(element: E): Arr<E, false>;
export { Arr as Array };
interface Arr<E extends RuntypeBase<unknown> = RuntypeBase<unknown>> extends Codec<Static<E>[]> {
readonly tag: 'array';
readonly element: E;
readonly isReadonly: false;
asReadonly(): ReadonlyArray<E>;
}
declare function Arr<TElement extends RuntypeBase<unknown>>(element: TElement): Arr<TElement>;
export declare function ReadonlyArray<TElement extends RuntypeBase<unknown>>(element: TElement): ReadonlyArray<TElement>;

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface Boolean extends Runtype<boolean> {
tag: 'boolean';
import { Codec } from '../runtype';
export interface Boolean extends Codec<boolean> {
readonly tag: 'boolean';
}

@@ -5,0 +5,0 @@ /**

@@ -1,10 +0,11 @@

import { Runtype, Static } from '../runtype';
import { RuntypeBase, Static, Codec } from '../runtype';
export declare const RuntypeName: unique symbol;
export interface Brand<B extends string, A extends Runtype> extends Runtype<Static<A> & {
export interface Brand<B extends string, A extends RuntypeBase<unknown>> extends Codec<Static<A> & {
[RuntypeName]: B;
}> {
tag: 'brand';
brand: B;
entity: A;
readonly tag: 'brand';
readonly brand: B;
readonly entity: A;
}
export declare function Brand<B extends string, A extends Runtype>(brand: B, entity: A): Brand<B, A>;
export declare function isBrandRuntype(runtype: RuntypeBase): runtype is Brand<string, RuntypeBase>;
export declare function Brand<B extends string, A extends RuntypeBase<unknown>>(brand: B, entity: A): Brand<B, A>;

@@ -1,18 +0,21 @@

import { Runtype, Static } from '../runtype';
import { RuntypeBase, Static, Codec } from '../runtype';
import { Unknown } from './unknown';
export declare type ConstraintCheck<A extends Runtype> = (x: Static<A>) => boolean | string;
export interface Constraint<A extends Runtype, T extends Static<A> = Static<A>, K = unknown> extends Runtype<T> {
tag: 'constraint';
underlying: A;
constraint(x: Static<A>): boolean | string;
export declare type ConstraintCheck<A extends RuntypeBase<unknown>> = (x: Static<A>) => boolean | string;
export declare function isConstraintRuntype(runtype: RuntypeBase): runtype is Constraint<RuntypeBase, unknown, unknown>;
export interface Constraint<TUnderlying extends RuntypeBase<unknown>, TConstrained extends Static<TUnderlying> = Static<TUnderlying>, TArgs = unknown> extends Codec<TConstrained> {
readonly tag: 'constraint';
readonly underlying: TUnderlying;
constraint(x: Static<TUnderlying>): boolean | string;
readonly name?: string;
readonly args?: TArgs;
}
export declare function Constraint<TUnderlying extends RuntypeBase<unknown>, TConstrained extends Static<TUnderlying> = Static<TUnderlying>, TArgs = unknown>(underlying: TUnderlying, constraint: ConstraintCheck<TUnderlying>, options?: {
name?: string;
args?: K;
args?: TArgs;
}): Constraint<TUnderlying, TConstrained, TArgs>;
export interface Guard<TConstrained, TArgs = unknown> extends Constraint<Unknown, TConstrained, TArgs> {
}
export declare function Constraint<A extends Runtype, T extends Static<A> = Static<A>, K = unknown>(underlying: A, constraint: ConstraintCheck<A>, options?: {
name?: string;
args?: K;
}): Constraint<A, T, K>;
export declare const Guard: <T, K = unknown>(guard: (x: unknown) => x is T, options?: {
export declare const Guard: <T, K = unknown>(test: (x: unknown) => x is T, options?: {
name?: string | undefined;
args?: K | undefined;
} | undefined) => Constraint<Unknown, T, K>;
} | undefined) => Guard<T, K>;

@@ -1,20 +0,14 @@

import { Runtype, Static } from '../runtype';
export interface StringDictionary<V extends Runtype> extends Runtype<{
[_: string]: Static<V>;
}> {
tag: 'dictionary';
key: 'string';
value: V;
import { String, Number, Record } from '..';
import { RuntypeBase } from '../runtype';
export interface StringDictionary<V extends RuntypeBase> extends Record<String, V> {
}
export interface NumberDictionary<V extends Runtype> extends Runtype<{
[_: number]: Static<V>;
}> {
tag: 'dictionary';
key: 'number';
value: V;
export interface NumberDictionary<V extends RuntypeBase> extends Record<Number, V> {
}
/**
* Construct a runtype for arbitrary dictionaries.
* @deprecated use Record(String, value)
*/
export declare function Dictionary<V extends Runtype>(value: V, key?: 'string'): StringDictionary<V>;
export declare function Dictionary<V extends Runtype>(value: V, key?: 'number'): NumberDictionary<V>;
export declare function Dictionary<V extends RuntypeBase>(value: V, key?: 'string'): StringDictionary<V>;
/**
* @deprecated use Record(Number, value)
*/
export declare function Dictionary<V extends RuntypeBase>(value: V, key?: 'number'): NumberDictionary<V>;

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface Function extends Runtype<(...args: any[]) => any> {
tag: 'function';
import { Codec } from '../runtype';
export interface Function extends Codec<(...args: any[]) => any> {
readonly tag: 'function';
}

@@ -5,0 +5,0 @@ /**

@@ -1,9 +0,9 @@

import { Runtype } from '../runtype';
import { Codec } from '../runtype';
export interface Constructor<V> {
new (...args: any[]): V;
}
export interface InstanceOf<V> extends Runtype<V> {
tag: 'instanceof';
ctor: Constructor<V>;
export interface InstanceOf<V = unknown> extends Codec<V> {
readonly tag: 'instanceof';
readonly ctor: Constructor<V>;
}
export declare function InstanceOf<V>(ctor: Constructor<V>): InstanceOf<V>;

@@ -1,54 +0,12 @@

import { Runtype, Static } from '../runtype';
export interface Intersect1<A extends Runtype> extends Runtype<Static<A>> {
tag: 'intersect';
intersectees: [A];
import { Static, RuntypeBase, Codec } from '../runtype';
export declare type StaticIntersect<TIntersectees extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TIntersectees]: TIntersectees[key] extends RuntypeBase ? (parameter: Static<TIntersectees[key]>) => any : unknown;
}[number] extends (k: infer I) => void ? I : never;
export interface Intersect<TIntersectees extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]> extends Codec<StaticIntersect<TIntersectees>> {
readonly tag: 'intersect';
readonly intersectees: TIntersectees;
}
export interface Intersect2<A extends Runtype, B extends Runtype> extends Runtype<Static<A> & Static<B>> {
tag: 'intersect';
intersectees: [A, B];
}
export interface Intersect3<A extends Runtype, B extends Runtype, C extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C>> {
tag: 'intersect';
intersectees: [A, B, C];
}
export interface Intersect4<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D>> {
tag: 'intersect';
intersectees: [A, B, C, D];
}
export interface Intersect5<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E>> {
tag: 'intersect';
intersectees: [A, B, C, D, E];
}
export interface Intersect6<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F];
}
export interface Intersect7<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G];
}
export interface Intersect8<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G> & Static<H>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H];
}
export interface Intersect9<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G> & Static<H> & Static<I>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H, I];
}
export interface Intersect10<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype, J extends Runtype> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G> & Static<H> & Static<I> & Static<J>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H, I, J];
}
/**
* Construct an intersection runtype from runtypes for its alternatives.
*/
export declare function Intersect<A extends Runtype>(A: A): Intersect1<A>;
export declare function Intersect<A extends Runtype, B extends Runtype>(A: A, B: B): Intersect2<A, B>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype>(A: A, B: B, C: C): Intersect3<A, B, C>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype>(A: A, B: B, C: C, D: D): Intersect4<A, B, C, D>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype>(A: A, B: B, C: C, D: D, E: E): Intersect5<A, B, C, D, E>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F): Intersect6<A, B, C, D, E, F>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Intersect7<A, B, C, D, E, F, G>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Intersect8<A, B, C, D, E, F, G, H>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Intersect9<A, B, C, D, E, F, G, H, I>;
export declare function Intersect<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype, J extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J): Intersect10<A, B, C, D, E, F, G, H, I, J>;
export declare function Intersect<TIntersectees extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]>(...intersectees: TIntersectees): Intersect<TIntersectees>;

@@ -1,5 +0,11 @@

import { Runtype } from '../runtype';
import { RuntypeBase, Codec, Static } from '../runtype';
export interface Lazy<TUnderlying extends RuntypeBase<unknown>> extends Codec<Static<TUnderlying>> {
readonly tag: 'lazy';
readonly underlying: () => TUnderlying;
}
export declare function lazyValue<T>(fn: () => T): () => T;
export declare function isLazyRuntype(runtype: RuntypeBase): runtype is Lazy<RuntypeBase>;
/**
* Construct a possibly-recursive Runtype.
*/
export declare function Lazy<A extends Runtype>(delayed: () => A): A;
export declare function Lazy<TUnderlying extends RuntypeBase<unknown>>(delayed: () => TUnderlying): Lazy<TUnderlying>;

@@ -1,14 +0,15 @@

import { Runtype } from '../runtype';
import { RuntypeBase, Codec } from '../runtype';
/**
* The super type of all literal types.
*/
export declare type LiteralBase = undefined | null | boolean | number | string;
export interface Literal<A extends LiteralBase> extends Runtype<A> {
tag: 'literal';
value: A;
export declare type LiteralValue = undefined | null | boolean | number | string;
export interface Literal<TLiteralValue extends LiteralValue = LiteralValue> extends Codec<TLiteralValue> {
readonly tag: 'literal';
readonly value: TLiteralValue;
}
export declare function isLiteralRuntype(runtype: RuntypeBase): runtype is Literal;
/**
* Construct a runtype for a type literal.
*/
export declare function Literal<A extends LiteralBase>(valueBase: A): Literal<A>;
export declare function Literal<A extends LiteralValue>(valueBase: A): Literal<A>;
/**

@@ -15,0 +16,0 @@ * An alias for Literal(undefined).

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface Never extends Runtype<never> {
tag: 'never';
import { Codec } from '../runtype';
export interface Never extends Codec<never> {
readonly tag: 'never';
}

@@ -5,0 +5,0 @@ /**

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface Number extends Runtype<number> {
tag: 'number';
import { Codec } from '../runtype';
export interface Number extends Codec<number> {
readonly tag: 'number';
}

@@ -5,0 +5,0 @@ /**

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface String extends Runtype<string> {
tag: 'string';
import { Codec } from '../runtype';
export interface String extends Codec<string> {
readonly tag: 'string';
}

@@ -5,0 +5,0 @@ /**

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
interface Sym extends Runtype<symbol> {
tag: 'symbol';
import { Codec } from '../runtype';
interface Sym extends Codec<symbol> {
readonly tag: 'symbol';
}

@@ -5,0 +5,0 @@ /**

@@ -1,59 +0,13 @@

import { Runtype, Static } from '../runtype';
export interface Tuple0 extends Runtype {
tag: 'tuple';
components: [];
import { RuntypeBase, Codec } from '../runtype';
export declare type StaticTuple<TElements extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TElements]: TElements[key] extends RuntypeBase<infer E> ? E : unknown;
};
export interface Tuple<TElements extends readonly RuntypeBase<unknown>[] = readonly RuntypeBase<unknown>[]> extends Codec<StaticTuple<TElements>> {
readonly tag: 'tuple';
readonly components: TElements;
}
export interface Tuple1<A extends Runtype> extends Runtype<[Static<A>]> {
tag: 'tuple';
components: [A];
}
export interface Tuple2<A extends Runtype, B extends Runtype> extends Runtype<[Static<A>, Static<B>]> {
tag: 'tuple';
components: [A, B];
}
export interface Tuple3<A extends Runtype, B extends Runtype, C extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>]> {
tag: 'tuple';
components: [A, B, C];
}
export interface Tuple4<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>]> {
tag: 'tuple';
components: [A, B, C, D];
}
export interface Tuple5<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>]> {
tag: 'tuple';
components: [A, B, C, D, E];
}
export interface Tuple6<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>]> {
tag: 'tuple';
components: [A, B, C, D, E, F];
}
export interface Tuple7<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>]> {
tag: 'tuple';
components: [A, B, C, D, E, F, G];
}
export interface Tuple8<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>, Static<H>]> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H];
}
export interface Tuple9<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>, Static<H>, Static<I>]> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H, I];
}
export interface Tuple10<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype, J extends Runtype> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>, Static<H>, Static<I>, Static<J>]> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H, I, J];
}
export declare function isTupleRuntype(runtype: RuntypeBase): runtype is Tuple<readonly RuntypeBase[]>;
/**
* Construct a tuple runtype from runtypes for each of its elements.
*/
export declare function Tuple(): Tuple0;
export declare function Tuple<A extends Runtype>(A: A): Tuple1<A>;
export declare function Tuple<A extends Runtype, B extends Runtype>(A: A, B: B): Tuple2<A, B>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype>(A: A, B: B, C: C): Tuple3<A, B, C>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype>(A: A, B: B, C: C, D: D): Tuple4<A, B, C, D>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype>(A: A, B: B, C: C, D: D, E: E): Tuple5<A, B, C, D, E>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F): Tuple6<A, B, C, D, E, F>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Tuple7<A, B, C, D, E, F, G>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Tuple8<A, B, C, D, E, F, G, H>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Tuple9<A, B, C, D, E, F, G, H, I>;
export declare function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype, E extends Runtype, F extends Runtype, G extends Runtype, H extends Runtype, I extends Runtype, J extends Runtype>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J): Tuple10<A, B, C, D, E, F, G, H, I, J>;
export declare function Tuple<T extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]] | readonly []>(...components: T): Tuple<T>;

@@ -1,205 +0,22 @@

import { Runtype as Rt, Static } from '../runtype';
export interface Union1<A extends Rt> extends Rt<Static<A>> {
tag: 'union';
alternatives: [A];
match: Match1<A>;
import { Codec, Static, RuntypeBase } from '../runtype';
export declare type StaticUnion<TAlternatives extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TAlternatives]: TAlternatives[key] extends RuntypeBase<unknown> ? Static<TAlternatives[key]> : unknown;
}[number];
export interface Union<TAlternatives extends readonly RuntypeBase<unknown>[]> extends Codec<StaticUnion<TAlternatives>> {
readonly tag: 'union';
readonly alternatives: TAlternatives;
match: Match<TAlternatives>;
}
export interface Union2<A extends Rt, B extends Rt> extends Rt<Static<A> | Static<B>> {
tag: 'union';
alternatives: [A, B];
match: Match2<A, B>;
}
export interface Union3<A extends Rt, B extends Rt, C extends Rt> extends Rt<Static<A> | Static<B> | Static<C>> {
tag: 'union';
alternatives: [A, B, C];
match: Match3<A, B, C>;
}
export interface Union4<A extends Rt, B extends Rt, C extends Rt, D extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D>> {
tag: 'union';
alternatives: [A, B, C, D];
match: Match4<A, B, C, D>;
}
export interface Union5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E>> {
tag: 'union';
alternatives: [A, B, C, D, E];
match: Match5<A, B, C, D, E>;
}
export interface Union6<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F>> {
tag: 'union';
alternatives: [A, B, C, D, E, F];
match: Match6<A, B, C, D, E, F>;
}
export interface Union7<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G];
match: Match7<A, B, C, D, E, F, G>;
}
export interface Union8<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H];
match: Match8<A, B, C, D, E, F, G, H>;
}
export interface Union9<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I];
match: Match9<A, B, C, D, E, F, G, H, I>;
}
export interface Union10<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J];
match: Match10<A, B, C, D, E, F, G, H, I, J>;
}
export interface Union11<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K];
match: Match11<A, B, C, D, E, F, G, H, I, J, K>;
}
export interface Union12<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L];
match: Match12<A, B, C, D, E, F, G, H, I, J, K, L>;
}
export interface Union13<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M];
match: Match13<A, B, C, D, E, F, G, H, I, J, K, L, M>;
}
export interface Union14<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N];
match: Match14<A, B, C, D, E, F, G, H, I, J, K, L, M, N>;
}
export interface Union15<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O];
match: Match15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>;
}
export interface Union16<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P];
match: Match16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>;
}
export interface Union17<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q];
match: Match17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>;
}
export interface Union18<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R];
match: Match18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R>;
}
export interface Union19<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R> | Static<S>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S];
match: Match19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S>;
}
export interface Union20<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt, T extends Rt> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R> | Static<S> | Static<T>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T];
match: Match20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T>;
}
/**
* Construct a union runtype from runtypes for its alternatives.
*/
export declare function Union<A extends Rt>(A: A): Union1<A>;
export declare function Union<A extends Rt, B extends Rt>(A: A, B: B): Union2<A, B>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt>(A: A, B: B, C: C): Union3<A, B, C>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt>(A: A, B: B, C: C, D: D): Union4<A, B, C, D>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt>(A: A, B: B, C: C, D: D, E: E): Union5<A, B, C, D, E>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F): Union6<A, B, C, D, E, F>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Union7<A, B, C, D, E, F, G>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Union8<A, B, C, D, E, F, G, H>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Union9<A, B, C, D, E, F, G, H, I>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J): Union10<A, B, C, D, E, F, G, H, I, J>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K): Union11<A, B, C, D, E, F, G, H, I, J, K>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L): Union12<A, B, C, D, E, F, G, H, I, J, K, L>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M): Union13<A, B, C, D, E, F, G, H, I, J, K, L, M>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N): Union14<A, B, C, D, E, F, G, H, I, J, K, L, M, N>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O): Union15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O, P: P): Union16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O, P: P, Q: Q): Union17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O, P: P, Q: Q, R: R): Union18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O, P: P, Q: Q, R: R, S: S): Union19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S>;
export declare function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt, T extends Rt>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I, J: J, K: K, L: L, M: M, N: N, O: O, P: P, Q: Q, R: R, S: S, T: T): Union20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T>;
export interface Match1<A extends Rt> {
<Z>(a: Case<A, Z>): Matcher1<A, Z>;
export declare function Union<TAlternatives extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]>(...alternatives: TAlternatives): Union<TAlternatives>;
export interface Match<A extends readonly RuntypeBase<unknown>[]> {
<Z>(...a: {
[key in keyof A]: A[key] extends RuntypeBase<unknown> ? Case<A[key], Z> : never;
}): Matcher<A, Z>;
}
export interface Match2<A extends Rt, B extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>): Matcher2<A, B, Z>;
}
export interface Match3<A extends Rt, B extends Rt, C extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>): Matcher3<A, B, C, Z>;
}
export interface Match4<A extends Rt, B extends Rt, C extends Rt, D extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>): Matcher4<A, B, C, D, Z>;
}
export interface Match5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>): Matcher5<A, B, C, D, E, Z>;
}
export interface Match6<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>): Matcher6<A, B, C, D, E, F, Z>;
}
export interface Match7<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>, g: Case<G, Z>): Matcher7<A, B, C, D, E, F, G, Z>;
}
export interface Match8<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>, g: Case<G, Z>, h: Case<H, Z>): Matcher8<A, B, C, D, E, F, G, H, Z>;
}
export interface Match9<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>, g: Case<G, Z>, h: Case<H, Z>, i: Case<I, Z>): Matcher9<A, B, C, D, E, F, G, H, I, Z>;
}
export interface Match10<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>, g: Case<G, Z>, h: Case<H, Z>, i: Case<I, Z>, j: Case<J, Z>): Matcher10<A, B, C, D, E, F, G, H, I, J, Z>;
}
export interface Match11<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>, f: Case<F, Z>, g: Case<G, Z>, h: Case<H, Z>, i: Case<I, Z>, j: Case<J, Z>, k: Case<K, Z>): Matcher11<A, B, C, D, E, F, G, H, I, J, K, Z>;
}
export interface Match12<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>): Matcher12<A, B, C, D, E, F, G, H, I, J, K, L, Z>;
}
export interface Match13<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>): Matcher13<A, B, C, D, E, F, G, H, I, J, K, L, M, Z>;
}
export interface Match14<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>): Matcher14<A, B, C, D, E, F, G, H, I, J, K, L, M, N, Z>;
}
export interface Match15<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>): Matcher15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Z>;
}
export interface Match16<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>, P: Case<P, Z>): Matcher16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Z>;
}
export interface Match17<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>, P: Case<P, Z>, Q: Case<Q, Z>): Matcher17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Z>;
}
export interface Match18<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>, P: Case<P, Z>, Q: Case<Q, Z>, R: Case<R, Z>): Matcher18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Z>;
}
export interface Match19<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>, P: Case<P, Z>, Q: Case<Q, Z>, R: Case<R, Z>, S: Case<S, Z>): Matcher19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Z>;
}
export interface Match20<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt, T extends Rt> {
<Z>(A: Case<A, Z>, B: Case<B, Z>, C: Case<C, Z>, D: Case<D, Z>, E: Case<E, Z>, F: Case<F, Z>, G: Case<G, Z>, H: Case<H, Z>, I: Case<I, Z>, J: Case<J, Z>, K: Case<K, Z>, L: Case<L, Z>, M: Case<M, Z>, N: Case<N, Z>, O: Case<O, Z>, P: Case<P, Z>, Q: Case<Q, Z>, R: Case<R, Z>, S: Case<S, Z>, T: Case<T, Z>): Matcher20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Z>;
}
export declare type Case<T extends Rt, Result> = (v: Static<T>) => Result;
export declare type Matcher1<A extends Rt, Z> = (x: Static<A>) => Z;
export declare type Matcher2<A extends Rt, B extends Rt, Z> = (x: Static<A> | Static<B>) => Z;
export declare type Matcher3<A extends Rt, B extends Rt, C extends Rt, Z> = (x: Static<A> | Static<B> | Static<C>) => Z;
export declare type Matcher4<A extends Rt, B extends Rt, C extends Rt, D extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D>) => Z;
export declare type Matcher5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E>) => Z;
export declare type Matcher6<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F>) => Z;
export declare type Matcher7<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G>) => Z;
export declare type Matcher8<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H>) => Z;
export declare type Matcher9<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I>) => Z;
export declare type Matcher10<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J>) => Z;
export declare type Matcher11<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K>) => Z;
export declare type Matcher12<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L>) => Z;
export declare type Matcher13<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M>) => Z;
export declare type Matcher14<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N>) => Z;
export declare type Matcher15<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O>) => Z;
export declare type Matcher16<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P>) => Z;
export declare type Matcher17<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q>) => Z;
export declare type Matcher18<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R>) => Z;
export declare type Matcher19<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R> | Static<S>) => Z;
export declare type Matcher20<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, F extends Rt, G extends Rt, H extends Rt, I extends Rt, J extends Rt, K extends Rt, L extends Rt, M extends Rt, N extends Rt, O extends Rt, P extends Rt, Q extends Rt, R extends Rt, S extends Rt, T extends Rt, Z> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H> | Static<I> | Static<J> | Static<K> | Static<L> | Static<M> | Static<N> | Static<O> | Static<P> | Static<Q> | Static<R> | Static<S> | Static<T>) => Z;
export declare type Case<T extends RuntypeBase<unknown>, Result> = (v: Static<T>) => Result;
export declare type Matcher<A extends readonly RuntypeBase<unknown>[], Z> = (x: {
[key in keyof A]: A[key] extends RuntypeBase<infer Type> ? Type : unknown;
}[number]) => Z;

@@ -1,4 +0,4 @@

import { Runtype } from '../runtype';
export interface Unknown extends Runtype {
tag: 'unknown';
import { Codec } from '../runtype';
export interface Unknown extends Codec<unknown> {
readonly tag: 'unknown';
}

@@ -5,0 +5,0 @@ /**

@@ -0,0 +0,0 @@ import { Unknown } from './unknown';

export declare function hasKey<K extends string>(k: K, o: {}): o is {
[_ in K]: {};
};
{
"name": "funtypes",
"version": "1.0.0",
"version": "2.0.0",
"description": "Runtime validation for static types",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
"types": "./lib/index.d.ts",
"scripts": {
"build": "tsc --pretty",
"postbuild": "tsc --noEmit && rimraf lib/**/*.spec.*",
"build": "rollup -c",
"format": "node scripts/format.js",

@@ -20,5 +22,9 @@ "test": "jest $([ \"$CI\" = true ] && echo --coverage || echo --watch)",

"jest": "24.9.0",
"prettier": "^1.19.1",
"prettier": "^2.1.1",
"rollup": "^2.26.11",
"rollup-plugin-size-snapshot": "^0.12.0",
"rollup-plugin-typescript2": "^0.27.2",
"ts-jest": "^24.1.0",
"typescript": "3.7.5"
"type-assertions": "^1.1.0",
"typescript": "4.0.2"
},

@@ -46,4 +52,3 @@ "keywords:": [

"testEnvironment": "node"
},
"dependencies": {}
}
}

@@ -10,2 +10,3 @@ # Funtypes

[![Build Status](https://img.shields.io/github/workflow/status/ForbesLindesay/funtypes/Test/master?style=for-the-badge)](https://github.com/ForbesLindesay/funtypes/actions?query=workflow%3ATest+branch%3Amaster)
[![Coveralls github branch](https://img.shields.io/coveralls/github/ForbesLindesay/funtypes/master?color=brightgreen&style=for-the-badge)](https://coveralls.io/github/ForbesLindesay/funtypes)
[![Rolling Versions](https://img.shields.io/badge/Rolling%20Versions-Enabled-brightgreen?style=for-the-badge)](https://rollingversions.com/ForbesLindesay/funtypes)

@@ -68,7 +69,7 @@ [![NPM version](https://img.shields.io/npm/v/funtypes?style=for-the-badge)](https://www.npmjs.com/package/funtypes)

```ts
import { Boolean, Number, String, Literal, Array, Tuple, Record, Union } from 'funtypes';
import { Boolean, Number, String, Literal, Array, Tuple, Object, Union } from 'funtypes';
const Vector = Tuple(Number, Number, Number);
const Asteroid = Record({
const Asteroid = Object({
type: Literal('asteroid'),

@@ -79,3 +80,3 @@ location: Vector,

const Planet = Record({
const Planet = Object({
type: Literal('planet'),

@@ -95,3 +96,3 @@ location: Vector,

const CrewMember = Record({
const CrewMember = Object({
name: String,

@@ -103,3 +104,3 @@ age: Number,

const Ship = Record({
const Ship = Object({
type: Literal('ship'),

@@ -165,3 +166,3 @@ location: Vector,

function disembark(obj: {}) {
if (SpaceObject.guard(obj)) {
if (SpaceObject.test(obj)) {
// obj: SpaceObject

@@ -273,3 +274,3 @@ if (obj.type === 'ship') {

use a lowest-common-denominator type that will pass validation for all expected
inputs of your constraint function or type guard. If there's no obvious
inputs of your constraint function or type test. If there's no obvious
lowest-common-denominator type, you can always use `Unknown` as the underlying

@@ -321,3 +322,3 @@ type, as shown in the `Buffer` examples above.

If a `Record` may or may not have some keys, we can declare the optional
If a `Object` may or may not have some keys, we can declare the optional
keys using `myRecord.And(Partial({ ... }))`. Partial keys validate successfully if

@@ -329,3 +330,3 @@ they are absent or undefined (but not null) or the type specified

// Using `Ship` from above
const RegisteredShip = Ship.And(Record({
const RegisteredShip = Ship.And(Object({
// All registered ships must have this flag

@@ -344,6 +345,6 @@ isRegistered: Literal(true),

If a record has keys which _must be present_ but can be null, then use
the `Record` runtype normally instead.
the `Object` runtype normally instead.
```ts
const MilitaryShip = Ship.And(Record({
const MilitaryShip = Ship.And(Object({
shipClass: Literal('military'),

@@ -358,3 +359,3 @@

Array and Record funtypes have a special function `.asReadonly()`, that creates a new runtype where the values are readonly.
Array and Object funtypes have a special function `.asReadonly()`, that creates a new runtype where the values are readonly.

@@ -364,3 +365,3 @@ For example:

```typescript
const Asteroid = Record({
const Asteroid = Object({
type: Literal('asteroid'),

@@ -367,0 +368,0 @@ location: Vector,

@@ -13,5 +13,3 @@ 'use strict';

const npmBinPath = execSync('npm bin')
.toString()
.trim();
const npmBinPath = execSync('npm bin').toString().trim();

@@ -18,0 +16,0 @@ const command = [

import { AsyncContract, Number } from '.';
import { ValidationError } from './errors';
describe('AsyncContract', () => {
describe('when function does not return a promise', () => {
it('throws a validation error', () => {
const contractedFunction = AsyncContract(Number).enforce(() => 7 as any);
expect(contractedFunction).toThrow(ValidationError);
it('throws a validation error', async () => {
const contractedFunction = AsyncContract([], Number).enforce(() => 7 as any);
await expect(contractedFunction()).rejects.toMatchInlineSnapshot(
`[ValidationError: Expected function to return a promise, but instead got 7]`,
);
});

@@ -13,14 +14,13 @@ });

it('throws a validation error asynchronously', async () => {
const contractedFunction = AsyncContract(Number).enforce(() => Promise.resolve('hi' as any));
try {
await contractedFunction();
fail();
} catch (e) {
expect(e).toBeInstanceOf(ValidationError);
}
const contractedFunction = AsyncContract([], Number).enforce(() =>
Promise.resolve('hi' as any),
);
await expect(contractedFunction()).rejects.toMatchInlineSnapshot(
`[ValidationError: Expected number, but was string]`,
);
});
});
describe('when a function does return a promise', () => {
describe('when a function does return a promise, for the correct type', () => {
it('should validate successfully', async () => {
const contractedFunction = AsyncContract(Number).enforce(() => Promise.resolve(7));
const contractedFunction = AsyncContract([], Number).enforce(() => Promise.resolve(7));
await expect(contractedFunction()).resolves.toBe(7);

@@ -30,7 +30,29 @@ });

describe('when not enough arguments are provided', () => {
it('throws a validation error', () => {
const contractedFunction = AsyncContract(Number, Number).enforce(n => Promise.resolve(n + 1));
expect(contractedFunction).toThrow(ValidationError);
it('throws a validation error', async () => {
const contractedFunction = AsyncContract([Number], Number).enforce(n =>
Promise.resolve(n + 1),
);
await expect((contractedFunction as any)()).rejects.toMatchInlineSnapshot(
`[ValidationError: Expected 1 arguments but only received 0]`,
);
});
});
describe('when arguments are of the wrong type', () => {
it('throws a validation error', async () => {
const contractedFunction = AsyncContract([Number], Number).enforce(n =>
Promise.resolve(n + 1),
);
await expect(contractedFunction('whatever' as any)).rejects.toMatchInlineSnapshot(
`[ValidationError: Expected number, but was string]`,
);
});
});
describe('when arguments are valid', () => {
it('throws a validation error', async () => {
const contractedFunction = AsyncContract([Number], Number).enforce(n =>
Promise.resolve(n + 1),
);
await expect(contractedFunction(41)).resolves.toEqual(42);
});
});
});

@@ -1,165 +0,57 @@

import { Runtype } from './index';
import { ValidationError } from './errors';
import {
createGuardVisitedState,
createVisitedState,
innerGuard,
innerValidate,
OpaqueVisitedState,
RuntypeBase,
} from './runtype';
export interface AsyncContract0<Z> {
enforce(f: () => Promise<Z>): () => Promise<Z>;
export interface AsyncContract<A extends any[], Z> {
enforce(f: (...a: A) => Promise<Z>): (...a: A) => Promise<Z>;
}
export interface AsyncContract1<A, Z> {
enforce(f: (a: A) => Promise<Z>): (a: A) => Promise<Z>;
}
export interface AsyncContract2<A, B, Z> {
enforce(f: (a: A, b: B) => Promise<Z>): (a: A, b: B) => Promise<Z>;
}
export interface AsyncContract3<A, B, C, Z> {
enforce(f: (a: A, b: B, c: C) => Promise<Z>): (a: A, b: B, c: C) => Promise<Z>;
}
export interface AsyncContract4<A, B, C, D, Z> {
enforce(f: (a: A, b: B, c: C, d: D) => Promise<Z>): (a: A, b: B, c: C, d: D) => Promise<Z>;
}
export interface AsyncContract5<A, B, C, D, E, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E) => Promise<Z>;
}
export interface AsyncContract6<A, B, C, D, E, F, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E, f: F) => Promise<Z>;
}
export interface AsyncContract7<A, B, C, D, E, F, G, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Promise<Z>;
}
export interface AsyncContract8<A, B, C, D, E, F, G, H, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Promise<Z>;
}
export interface AsyncContract9<A, B, C, D, E, F, G, H, I, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Promise<Z>;
}
export interface AsyncContract10<A, B, C, D, E, F, G, H, I, J, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<Z>,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Promise<Z>;
}
/**
* Create a function contract.
*/
export function AsyncContract<Z>(Z: Runtype<Z>): AsyncContract0<Z>;
export function AsyncContract<A, Z>(A: Runtype<A>, Z: Runtype<Z>): AsyncContract1<A, Z>;
export function AsyncContract<A, B, Z>(
A: Runtype<A>,
B: Runtype<B>,
Z: Runtype<Z>,
): AsyncContract2<A, B, Z>;
export function AsyncContract<A, B, C, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
Z: Runtype<Z>,
): AsyncContract3<A, B, C, Z>;
export function AsyncContract<A, B, C, D, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
Z: Runtype<Z>,
): AsyncContract4<A, B, C, D, Z>;
export function AsyncContract<A, B, C, D, E, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
Z: Runtype<Z>,
): AsyncContract5<A, B, C, D, E, Z>;
export function AsyncContract<A, B, C, D, E, F, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
Z: Runtype<Z>,
): AsyncContract6<A, B, C, D, E, F, Z>;
export function AsyncContract<A, B, C, D, E, F, G, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
Z: Runtype<Z>,
): AsyncContract7<A, B, C, D, E, F, G, Z>;
export function AsyncContract<A, B, C, D, E, F, G, H, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
Z: Runtype<Z>,
): AsyncContract8<A, B, C, D, E, F, G, H, Z>;
export function AsyncContract<A, B, C, D, E, F, G, H, I, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
I: Runtype<I>,
Z: Runtype<Z>,
): AsyncContract9<A, B, C, D, E, F, G, H, I, Z>;
export function AsyncContract<A, B, C, D, E, F, G, H, I, J, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
I: Runtype<I>,
J: Runtype<J>,
Z: Runtype<Z>,
): AsyncContract10<A, B, C, D, E, F, G, H, I, J, Z>;
export function AsyncContract(...runtypes: Runtype[]) {
const lastIndex = runtypes.length - 1;
const argTypes = runtypes.slice(0, lastIndex);
const returnType = runtypes[lastIndex];
export function AsyncContract<A extends [any, ...any[]] | [], Z>(
argTypes: { [key in keyof A]: key extends 'length' ? A['length'] : RuntypeBase<A[key]> },
returnType: RuntypeBase<Z>,
): AsyncContract<A, Z> {
return {
enforce: (f: (...args: any[]) => any) => (...args: any[]) => {
if (args.length < argTypes.length)
throw new ValidationError(
`Expected ${argTypes.length} arguments but only received ${args.length}`,
if (args.length < argTypes.length) {
return Promise.reject(
new ValidationError(
`Expected ${argTypes.length} arguments but only received ${args.length}`,
),
);
for (let i = 0; i < argTypes.length; i++) argTypes[i].check(args[i]);
}
const visited: OpaqueVisitedState = createVisitedState();
for (let i = 0; i < argTypes.length; i++) {
const result = innerValidate(argTypes[i], args[i], visited);
if (result.success) {
args[i] = result.value;
} else {
return Promise.reject(new ValidationError(result.message, result.key));
}
}
const returnedPromise = f(...args);
if (!(returnedPromise instanceof Promise))
throw new ValidationError(
`Expected function to return a promise, but instead got ${returnedPromise}`,
if (!(returnedPromise instanceof Promise)) {
return Promise.reject(
new ValidationError(
`Expected function to return a promise, but instead got ${returnedPromise}`,
),
);
return returnedPromise.then(returnType.check);
}
return returnedPromise.then(value => {
const result = innerGuard(returnType, value, createGuardVisitedState());
if (result) {
throw new ValidationError(result.message, result.key);
}
return value;
});
},
};
}

@@ -1,144 +0,24 @@

import { Runtype } from './index';
import {
createGuardVisitedState,
createVisitedState,
innerGuard,
innerValidate,
OpaqueVisitedState,
RuntypeBase,
} from './runtype';
import { ValidationError } from './errors';
export interface Contract0<Z> {
enforce(f: () => Z): () => Z;
export interface Contract<A extends any[], Z> {
enforce(f: (...a: A) => Z): (...a: A) => Z;
}
export interface Contract1<A, Z> {
enforce(f: (a: A) => Z): (a: A) => Z;
}
export interface Contract2<A, B, Z> {
enforce(f: (a: A, b: B) => Z): (a: A, b: B) => Z;
}
export interface Contract3<A, B, C, Z> {
enforce(f: (a: A, b: B, c: C) => Z): (a: A, b: B, c: C) => Z;
}
export interface Contract4<A, B, C, D, Z> {
enforce(f: (a: A, b: B, c: C, d: D) => Z): (a: A, b: B, c: C, d: D) => Z;
}
export interface Contract5<A, B, C, D, E, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E) => Z): (a: A, b: B, c: C, d: D, e: E) => Z;
}
export interface Contract6<A, B, C, D, E, F, Z> {
enforce(f: (a: A, b: B, c: C, d: D, e: E, f: F) => Z): (a: A, b: B, c: C, d: D, e: E, f: F) => Z;
}
export interface Contract7<A, B, C, D, E, F, G, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Z,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => Z;
}
export interface Contract8<A, B, C, D, E, F, G, H, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Z,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => Z;
}
export interface Contract9<A, B, C, D, E, F, G, H, I, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Z,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => Z;
}
export interface Contract10<A, B, C, D, E, F, G, H, I, J, Z> {
enforce(
f: (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Z,
): (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => Z;
}
/**
* Create a function contract.
*/
export function Contract<Z>(Z: Runtype<Z>): Contract0<Z>;
export function Contract<A, Z>(A: Runtype<A>, Z: Runtype<Z>): Contract1<A, Z>;
export function Contract<A, B, Z>(A: Runtype<A>, B: Runtype<B>, Z: Runtype<Z>): Contract2<A, B, Z>;
export function Contract<A, B, C, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
Z: Runtype<Z>,
): Contract3<A, B, C, Z>;
export function Contract<A, B, C, D, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
Z: Runtype<Z>,
): Contract4<A, B, C, D, Z>;
export function Contract<A, B, C, D, E, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
Z: Runtype<Z>,
): Contract5<A, B, C, D, E, Z>;
export function Contract<A, B, C, D, E, F, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
Z: Runtype<Z>,
): Contract6<A, B, C, D, E, F, Z>;
export function Contract<A, B, C, D, E, F, G, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
Z: Runtype<Z>,
): Contract7<A, B, C, D, E, F, G, Z>;
export function Contract<A, B, C, D, E, F, G, H, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
Z: Runtype<Z>,
): Contract8<A, B, C, D, E, F, G, H, Z>;
export function Contract<A, B, C, D, E, F, G, H, I, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
I: Runtype<I>,
Z: Runtype<Z>,
): Contract9<A, B, C, D, E, F, G, H, I, Z>;
export function Contract<A, B, C, D, E, F, G, H, I, J, Z>(
A: Runtype<A>,
B: Runtype<B>,
C: Runtype<C>,
D: Runtype<D>,
E: Runtype<E>,
F: Runtype<F>,
G: Runtype<G>,
H: Runtype<H>,
I: Runtype<I>,
J: Runtype<J>,
Z: Runtype<Z>,
): Contract10<A, B, C, D, E, F, G, H, I, J, Z>;
export function Contract(...runtypes: Runtype[]) {
const lastIndex = runtypes.length - 1;
const argTypes = runtypes.slice(0, lastIndex);
const returnType = runtypes[lastIndex];
export function Contract<A extends [any, ...any[]] | [], Z>(
argTypes: { [key in keyof A]: key extends 'length' ? A['length'] : RuntypeBase<A[key]> },
returnType: RuntypeBase<Z>,
): Contract<A, Z> {
return {
enforce: (f: (...args: any[]) => any) => (...args: any[]) => {
enforce: (f: (...args: A) => Z) => (...args: A): Z => {
if (args.length < argTypes.length)

@@ -148,6 +28,19 @@ throw new ValidationError(

);
for (let i = 0; i < argTypes.length; i++) argTypes[i].check(args[i]);
return returnType.check(f(...args));
const visited: OpaqueVisitedState = createVisitedState();
for (let i = 0; i < argTypes.length; i++) {
const result = innerValidate(argTypes[i], args[i], visited);
if (result.success) {
args[i] = result.value;
} else {
throw new ValidationError(result.message, result.key);
}
}
const rawResult = f(...args);
const result = innerGuard(returnType, rawResult, createGuardVisitedState());
if (result) {
throw new ValidationError(result.message, result.key);
}
return rawResult;
},
};
}
import {
Runtype,
Static,
Unknown,
Array,
Boolean,
Brand,
Constraint,
Contract,
Record,
Function,
Guard,
InstanceOf,
Intersect,
Lazy,
Literal,
Never,
Undefined,
Null,
Void,
Boolean,
Number,
Partial as RTPartial,
ReadonlyArray,
Object as ObjectType,
Runtype,
Static,
String,
Symbol as Sym,
Literal,
Array,
Dictionary,
Record,
Partial as RTPartial,
Tuple,
Tuple2,
Undefined,
Union,
Union2,
Intersect,
Intersect2,
Function,
Lazy,
Constraint,
Contract,
Reflect,
InstanceOf,
Brand,
Guard,
Unknown,
Void,
} from './index';

@@ -38,7 +35,7 @@

const boolTuple = Tuple(Boolean, Boolean, Boolean);
const record1 = Record({ Boolean, Number });
const union1 = Union(Literal(3), String, boolTuple, record1);
const object1 = ObjectType({ Boolean, Number });
const union1 = Union(Literal(3), String, boolTuple, object1);
type Person = { name: string; likes: Person[] };
const Person: Runtype<Person> = Lazy(() => Record({ name: String, likes: Array(Person) }));
const Person: Runtype<Person> = Lazy(() => ObjectType({ name: String, likes: Array(Person) }));
const narcissist: Person = { name: 'Narcissus', likes: [] };

@@ -59,4 +56,4 @@ narcissist.likes = [narcissist];

type SRDict = { [_: string]: SRDict };
const SRDict: Runtype<SRDict> = Lazy(() => Dictionary(SRDict));
type SRDict = { [_ in string]?: SRDict };
const SRDict: Runtype<SRDict> = Lazy(() => Record(String, SRDict));
const srDict: SRDict = {};

@@ -66,3 +63,5 @@ srDict['self'] = srDict;

type Hand = { left: Hand } | { right: Hand };
const Hand: Runtype<Hand> = Lazy(() => Union(Record({ left: Hand }), Record({ right: Hand })));
const Hand: Runtype<Hand> = Lazy(() =>
Union(ObjectType({ left: Hand }), ObjectType({ right: Hand })),
);
const leftHand: Hand = { left: (null as any) as Hand };

@@ -73,3 +72,5 @@ const rightHand: Hand = { right: leftHand };

type Ambi = { left: Ambi } & { right: Ambi };
const Ambi: Runtype<Ambi> = Lazy(() => Intersect(Record({ left: Ambi }), Record({ right: Ambi })));
const Ambi: Runtype<Ambi> = Lazy(() =>
Intersect(ObjectType({ left: Ambi }), ObjectType({ right: Ambi })),
);
const ambi: Ambi = { left: (null as any) as Ambi, right: (null as any) as Ambi };

@@ -110,3 +111,3 @@ ambi.left = ambi;

const runtypes = {
const runtypes: { [key: string]: Runtype<unknown> } = {
Unknown,

@@ -116,3 +117,3 @@ Never,

Null,
Empty: Record({}),
Empty: ObjectType({}),
Void,

@@ -132,5 +133,5 @@ Boolean,

boolTuple,
record1,
object1,
union1,
Partial: RTPartial({ foo: String }).And(Record({ Boolean })),
Partial: RTPartial({ foo: String }).And(ObjectType({ Boolean })),
Function,

@@ -148,5 +149,5 @@ Person,

),
Dictionary: Dictionary(String),
NumberDictionary: Dictionary(String, 'number'),
DictionaryOfArrays: Dictionary(Array(Boolean)),
Record: Record(String, String),
NumberRecord: Record(Number, String),
RecordOfArrays: Record(String, Array(Boolean)),
InstanceOfSomeClass: InstanceOf(SomeClass),

@@ -170,6 +171,6 @@ InstanceOfSomeOtherClass: InstanceOf(SomeOtherClass),

),
DictionaryOfArraysOfSomeClass: Dictionary(Array(InstanceOf(SomeClass))),
OptionalKey: Record({ foo: String, bar: Union(Number, Undefined) }),
RecordOfArraysOfSomeClass: Record(String, Array(InstanceOf(SomeClass))),
OptionalKey: ObjectType({ foo: String, bar: Union(Number, Undefined) }),
ReadonlyNumberArray: Array(Number).asReadonly(),
ReadonlyRecord: Record({ foo: Number, bar: String }).asReadonly(),
ReadonlyRecord: ObjectType({ foo: Number, bar: String }).asReadonly(),
Graph,

@@ -181,3 +182,3 @@ SRDict,

PartialPerson,
ReadonlyPartial: Record({ foo: Number })
ReadonlyPartial: ObjectType({ foo: Number })
.asReadonly()

@@ -194,3 +195,3 @@ .And(RTPartial({ bar: String }).asReadonly()),

x!: 'blah';
} // Should not be recognized as a Dictionary
} // Should not be recognized as a Record

@@ -211,24 +212,24 @@ const testValues: { value: unknown; passes: RuntypeName[] }[] = [

{ value: [true, false, true], passes: ['boolArray', 'boolTuple', 'union1'] },
{ value: { Boolean: true, Number: 3 }, passes: ['record1', 'union1', 'Partial'] },
{ value: { Boolean: true }, passes: ['Partial'] },
{ value: { Boolean: true, foo: undefined }, passes: ['Partial'] },
{ value: { Boolean: true, foo: 'hello' }, passes: ['Partial', 'OptionalKey'] },
{ value: { Boolean: true, foo: 5 }, passes: ['ReadonlyPartial'] },
{ value: { Boolean: true, Number: 3 }, passes: ['object1', 'union1', 'Partial', 'Empty'] },
{ value: { Boolean: true }, passes: ['Partial', 'Empty'] },
{ value: { Boolean: true, foo: undefined }, passes: ['Partial', 'Empty'] },
{ value: { Boolean: true, foo: 'hello' }, passes: ['Partial', 'OptionalKey', 'Empty'] },
{ value: { Boolean: true, foo: 5 }, passes: ['ReadonlyPartial', 'Empty'] },
{ value: (x: number, y: string) => x + y.length, passes: ['Function'] },
{ value: { name: undefined, likes: [] }, passes: [] },
{ value: { name: 'Jimmy', likes: [{ name: undefined, likes: [] }] }, passes: [] },
{ value: { name: undefined, likes: [] }, passes: ['Empty'] },
{ value: { name: 'Jimmy', likes: [{ name: undefined, likes: [] }] }, passes: ['Empty'] },
{
value: { name: 'Jimmy', likes: [{ name: 'Peter', likes: [] }] },
passes: ['Person'],
passes: ['Person', 'Empty'],
},
{ value: { a: '1', b: '2' }, passes: ['Dictionary'] },
{ value: ['1', '2'], passes: ['ArrayString', 'NumberDictionary'] },
{ value: { a: '1', b: '2' }, passes: ['Record', 'Empty'] },
{ value: ['1', '2'], passes: ['ArrayString'] },
{ value: ['1', 2], passes: [] },
{ value: [{ name: 'Jimmy', likes: [{ name: 'Peter', likes: [] }] }], passes: ['ArrayPerson'] },
{ value: [{ name: null, likes: [] }], passes: [] },
{ value: { 1: '1', 2: '2' }, passes: ['Dictionary', 'NumberDictionary'] },
{ value: { a: [], b: [true, false] }, passes: ['DictionaryOfArrays'] },
{ value: new Foo(), passes: [] },
{ value: { 1: '1', 2: '2' }, passes: ['Record', 'NumberRecord', 'Empty'] },
{ value: { a: [], b: [true, false] }, passes: ['RecordOfArrays', 'Empty'] },
{ value: new Foo(), passes: ['Empty'] },
{ value: [1, 2, 4], passes: ['ArrayNumber', 'ReadonlyNumberArray'] },
{ value: { Boolean: true, Number: '5' }, passes: ['Partial'] },
{ value: { Boolean: true, Number: '5' }, passes: ['Partial', 'Empty'] },
{

@@ -246,2 +247,3 @@ value: [1, 2, 3, 4],

'GuardChangeTypeAndName',
'Empty',
],

@@ -257,16 +259,17 @@ },

'GuardChangeTypeAndName',
'Empty',
],
},
{ value: { xxx: [new SomeClass(55)] }, passes: ['DictionaryOfArraysOfSomeClass'] },
{ value: { foo: 'hello' }, passes: ['OptionalKey', 'Dictionary'] },
{ value: { foo: 'hello', bar: undefined }, passes: ['OptionalKey'] },
{ value: { foo: 4, bar: 'baz' }, passes: ['ReadonlyRecord', 'ReadonlyPartial'] },
{ value: narcissist, passes: ['Person'] },
{ value: { xxx: [new SomeClass(55)] }, passes: ['RecordOfArraysOfSomeClass', 'Empty'] },
{ value: { foo: 'hello' }, passes: ['OptionalKey', 'Record', 'Empty'] },
{ value: { foo: 'hello', bar: undefined }, passes: ['OptionalKey', 'Empty'] },
{ value: { foo: 4, bar: 'baz' }, passes: ['ReadonlyRecord', 'ReadonlyPartial', 'Empty'] },
{ value: narcissist, passes: ['Person', 'Empty'] },
{ value: [narcissist, narcissist], passes: ['ArrayPerson'] },
{ value: barbell, passes: ['Graph'] },
{ value: nodeA, passes: ['Graph', 'BarbellBall'] },
{ value: srDict, passes: ['SRDict'] },
{ value: leftHand, passes: ['Hand', 'SRDict'] },
{ value: ambi, passes: ['Ambi', 'Hand', 'SRDict'] },
{ value: partialNarcissus, passes: ['PartialPerson'] },
{ value: srDict, passes: ['SRDict', 'Empty'] },
{ value: leftHand, passes: ['Hand', 'SRDict', 'Empty'] },
{ value: ambi, passes: ['Ambi', 'Hand', 'SRDict', 'Empty'] },
{ value: partialNarcissus, passes: ['PartialPerson', 'Empty'] },
];

@@ -290,17 +293,14 @@

value === undefined ? 'undefined' : JSON.stringify(value, getCircularReplacer());
describe(`${valueName}`, () => {
const shouldPass: { [_ in RuntypeName]?: boolean } = {};
const shouldPass: { [_ in RuntypeName]?: boolean } = {};
shouldPass.Unknown = true;
shouldPass.Void = true;
shouldPass.Unknown = true;
shouldPass.Void = true;
if (value !== undefined && value !== null) shouldPass.Empty = true;
for (const name of passes) shouldPass[name] = true;
for (const name of passes) shouldPass[name] = true;
describe(`${valueName} - ${Object.keys(shouldPass).join(', ')}`, () => {
for (const name of runtypeNames) {
if (shouldPass[name]) {
it(` : ${name}`, () => assertAccepts(value, runtypes[name]));
it(`should be valid for ${name}`, () => assertAccepts(value, runtypes[name]));
} else {
it(`~: ${name}`, () => assertRejects(value, runtypes[name]));
it(`should NOT be valid for ${name}`, () => assertRejects(value, runtypes[name]));
}

@@ -314,5 +314,5 @@ }

const f = () => 3;
expect(Contract(Number).enforce(f)()).toBe(3);
expect(Contract([], Number).enforce(f)()).toBe(3);
try {
Contract(String).enforce(f as any)();
Contract([], String).enforce(f as any)();
fail('contract was violated but no exception was thrown');

@@ -327,5 +327,5 @@ } catch (exception) {

const f = (x: string) => x.length;
expect(Contract(String, Number).enforce(f)('hel')).toBe(3);
expect(Contract([String], Number).enforce(f)('hel')).toBe(3);
try {
(Contract(String, Number).enforce(f) as any)(3);
(Contract([String], Number).enforce(f) as any)(3);
fail('contract was violated but no exception was thrown');

@@ -340,5 +340,5 @@ } catch (exception) {

const f = (x: string, y: boolean) => (y ? x.length : 4);
expect(Contract(String, Boolean, Number).enforce(f)('hello', false)).toBe(4);
expect(Contract([String, Boolean], Number).enforce(f)('hello', false)).toBe(4);
try {
(Contract(String, Boolean, Number).enforce(f) as any)('hello');
(Contract([String, Boolean], Number).enforce(f) as any)('hello');
fail('contract was violated but no exception was thrown');

@@ -373,3 +373,3 @@ } catch (exception) {

[0, { name: 0 }],
Tuple(Number, Record({ name: String })),
Tuple(Number, ObjectType({ name: String })),
'Expected string, but was number in [1].name',

@@ -391,3 +391,3 @@ '[1].name',

[{ name: 'Foo' }, { name: false }],
Array(Record({ name: String })),
Array(ObjectType({ name: String })),
'Expected string, but was boolean in [1].name',

@@ -401,3 +401,3 @@ '[1].name',

[{ name: 'Foo' }, null],
Array(Record({ name: String })),
Array(ObjectType({ name: String })),
'Expected { name: string; }, but was null in [1]',

@@ -420,3 +420,3 @@ '[1]',

[{ name: 'Foo' }, { name: false }],
Array(Record({ name: String })).asReadonly(),
Array(ObjectType({ name: String })).asReadonly(),
'Expected string, but was boolean in [1].name',

@@ -430,3 +430,3 @@ '[1].name',

[{ name: 'Foo' }, null],
Array(Record({ name: String })).asReadonly(),
Array(ObjectType({ name: String })).asReadonly(),
'Expected { name: string; }, but was null in [1]',

@@ -438,3 +438,3 @@ '[1]',

it('dictionary', () => {
assertThrows(null, Dictionary(String), 'Expected { [_: string]: string }, but was null');
assertThrows(null, Record(String, String), 'Expected { [_: string]: string }, but was null');
});

@@ -445,3 +445,3 @@

undefined,
Dictionary(Record({ name: String })),
Record(String, ObjectType({ name: String })),
'Expected { [_: string]: { name: string; } }, but was undefined',

@@ -451,3 +451,3 @@ );

1,
Dictionary(Record({ name: String })),
Record(String, ObjectType({ name: String })),
'Expected { [_: string]: { name: string; } }, but was number',

@@ -460,3 +460,3 @@ );

{ foo: { name: false } },
Dictionary(Record({ name: String })),
Record(String, ObjectType({ name: String })),
'Expected string, but was boolean in foo.name',

@@ -470,3 +470,3 @@ 'foo.name',

{ foo: 'bar', test: true },
Dictionary(String),
Record(String, String),
'Expected string, but was boolean in test',

@@ -480,3 +480,3 @@ 'test',

{ 1: 'bar', 2: 20 },
Dictionary(String, 'number'),
Record(Number, String),
'Expected string, but was number in 2',

@@ -487,6 +487,6 @@ '2',

it('record', () => {
it('object', () => {
assertThrows(
{ name: 'Jack', age: '10' },
Record({
ObjectType({
name: String,

@@ -500,6 +500,6 @@ age: Number,

it('record missing keys', () => {
it('object missing keys', () => {
assertThrows(
{ name: 'Jack' },
Record({
ObjectType({
name: String,

@@ -513,9 +513,9 @@ age: Number,

it('record complex', () => {
it('object complex', () => {
assertThrows(
{ name: 'Jack', age: 10, likes: [{ title: false }] },
Record({
ObjectType({
name: String,
age: Number,
likes: Array(Record({ title: String })),
likes: Array(ObjectType({ title: String })),
}),

@@ -527,6 +527,6 @@ 'Expected string, but was boolean in likes.[0].title',

it('readonly record', () => {
it('readonly object', () => {
assertThrows(
{ name: 'Jack', age: '10' },
Record({
ObjectType({
name: String,

@@ -540,6 +540,6 @@ age: Number,

it('readonly record missing keys', () => {
it('readonly object missing keys', () => {
assertThrows(
{ name: 'Jack' },
Record({
ObjectType({
name: String,

@@ -553,9 +553,9 @@ age: Number,

it('readonly record complex', () => {
it('readonly object complex', () => {
assertThrows(
{ name: 'Jack', age: 10, likes: [{ title: false }] },
Record({
ObjectType({
name: String,
age: Number,
likes: Array(Record({ title: String }).asReadonly()),
likes: Array(ObjectType({ title: String }).asReadonly()),
}).asReadonly(),

@@ -585,3 +585,3 @@ 'Expected string, but was boolean in likes.[0].title',

age: Number,
likes: Array(Record({ title: String })),
likes: Array(ObjectType({ title: String })),
}),

@@ -676,16 +676,16 @@ 'Expected string, but was number in likes.[0].title',

it('string dictionary', () => {
const Rec = Dictionary(Unknown);
expectLiteralField(Rec, 'tag', 'dictionary');
expectLiteralField(Rec, 'key', 'string');
const Rec = Record(String, Unknown);
expectLiteralField(Rec, 'tag', 'record');
expectLiteralField(Rec.key, 'tag', 'string');
});
it('number dictionary', () => {
const Rec = Dictionary(Unknown, 'number');
expectLiteralField(Rec, 'tag', 'dictionary');
expectLiteralField(Rec, 'key', 'number');
const Rec = Record(Number, Unknown);
expectLiteralField(Rec, 'tag', 'record');
expectLiteralField(Rec.key, 'tag', 'number');
});
it('record', () => {
const Rec = Record({ x: Number, y: Literal(3) });
expectLiteralField(Rec, 'tag', 'record');
it('object', () => {
const Rec = ObjectType({ x: Number, y: Literal(3) });
expectLiteralField(Rec, 'tag', 'object');
expectLiteralField(Rec.fields.x, 'tag', 'number');

@@ -697,5 +697,5 @@ expectLiteralField(Rec.fields.y, 'tag', 'literal');

it('record (asReadonly)', () => {
const Rec = Record({ x: Number, y: Literal(3) }).asReadonly();
expectLiteralField(Rec, 'tag', 'record');
it('object (asReadonly)', () => {
const Rec = ObjectType({ x: Number, y: Literal(3) }).asReadonly();
expectLiteralField(Rec, 'tag', 'object');
expectLiteralField(Rec.fields.x, 'tag', 'number');

@@ -709,3 +709,3 @@ expectLiteralField(Rec.fields.y, 'tag', 'literal');

const Opt = RTPartial({ x: Number, y: Literal(3) });
expectLiteralField(Opt, 'tag', 'record');
expectLiteralField(Opt, 'tag', 'object');
expectLiteralField(Opt.fields.x, 'tag', 'number');

@@ -736,4 +736,5 @@ expectLiteralField(Opt.fields.y, 'tag', 'literal');

const L = Lazy(() => X);
expectLiteralField(L, 'tag', 'literal');
expectLiteralField(L, 'value', 'x');
expectLiteralField(L, 'tag', 'lazy');
expectLiteralField(L.underlying(), 'tag', 'literal');
expectLiteralField(L.underlying(), 'value', 'x');
});

@@ -751,3 +752,3 @@

expectLiteralField(InstanceOf(Test), 'tag', 'instanceof');
expectLiteralField(Dictionary(Array(InstanceOf(Test))), 'tag', 'dictionary');
expectLiteralField(Record(String, Array(InstanceOf(Test))), 'tag', 'record');
});

@@ -768,3 +769,3 @@

if (C.guard(value)) {
if (C.test(value)) {
return value;

@@ -795,17 +796,18 @@ } else {

| Literal<boolean | number | string>
| Array<Reflect, false>
| Array<Reflect, true>
| Record<{ [_ in string]: Reflect }, false>
| Record<{ [_ in string]: Reflect }, true>
| RTPartial<{ [_ in string]: Reflect }, false>
| RTPartial<{ [_ in string]: Reflect }, true>
| Tuple2<Reflect, Reflect>
| Union2<Reflect, Reflect>
| Intersect2<Reflect, Reflect>
| Array<String | Number>
| ReadonlyArray<String | Number>
| ObjectType<{ [_ in string]: String | Number }, false>
| ObjectType<{ [_ in string]: String | Number }, true>
| RTPartial<{ [_ in string]: String | Number }, false>
| RTPartial<{ [_ in string]: String | Number }, true>
| Tuple<[String, String | Number]>
| Union<[String, String | Number]>
| Intersect<[String | Number, String | Number]>
| Function
| Constraint<Reflect, any, any>
| Constraint<String | Number, any, any>
| InstanceOf<Constructor<never>>
| Brand<string, Reflect>,
): Reflect => {
const check = <A>(X: Runtype<A>): A => X.check({});
| Brand<string, String | Number>,
) => {
const check = <A>(X: Runtype<A>): A => X.parse({});
switch (X.tag) {

@@ -834,6 +836,10 @@ case 'unknown':

case 'array':
check<ReadonlyArray<Static<typeof X.element>>>(X);
check<readonly Static<typeof X.element>[]>(X);
break;
case 'record':
check<{ readonly [K in keyof typeof X.fields]: Static<typeof X.fields[K]> }>(X);
case 'object':
if (X.isPartial) {
check<{ readonly [K in keyof typeof X.fields]?: Static<typeof X.fields[K]> }>(X);
} else {
check<{ readonly [K in keyof typeof X.fields]: Static<typeof X.fields[K]> }>(X);
}
break;

@@ -862,4 +868,2 @@ case 'tuple':

}
return X;
};

@@ -872,3 +876,3 @@

function assertAccepts<A>(value: unknown, runtype: Runtype<A>) {
const result = runtype.validate(value);
const result = runtype.safeParse(value);
if (result.success === false) fail(result.message);

@@ -878,3 +882,3 @@ }

function assertRejects<A>(value: unknown, runtype: Runtype<A>) {
const result = runtype.validate(value);
const result = runtype.safeParse(value);
if (result.success === true) fail('value passed validation even though it was not expected to');

@@ -885,3 +889,3 @@ }

try {
runtype.check(value);
runtype.parse(value);
fail('value passed validation even though it was not expected to');

@@ -888,0 +892,0 @@ } catch (exception) {

@@ -1,27 +0,34 @@

export { Runtype, Static } from './runtype';
export * from './reflect';
export * from './result';
export * from './contract';
export * from './asynccontract';
export * from './match';
export * from './errors';
export * from './types/unknown';
export * from './types/never';
export * from './types/void';
export { Literal, Undefined, Null } from './types/literal';
export * from './types/boolean';
export * from './types/number';
export * from './types/string';
export * from './types/symbol';
export * from './types/array';
export * from './types/tuple';
export * from './types/record';
export * from './types/dictionary';
export * from './types/union';
export * from './types/intersect';
export * from './types/function';
export { AsyncContract } from './asynccontract';
export { Contract } from './contract';
export { assertType } from './assertType';
export type { Runtype, Codec, Static } from './runtype';
export type { Success, Failure, Result } from './result';
export { ValidationError } from './errors';
// TODO: should we export StaticIntersect, StaticTuple, StaticUnion etc.
export { Array, ReadonlyArray } from './types/array';
export { Boolean } from './types/boolean';
export type { ConstraintCheck } from './types/constraint';
export { Constraint, Guard } from './types/constraint';
export { Dictionary } from './types/dictionary';
export { Function } from './types/function';
export { InstanceOf } from './types/instanceof';
export * from './types/lazy';
export * from './types/constraint';
export { Intersect } from './types/intersect';
export { Lazy } from './types/lazy';
export type { LiteralValue } from './types/literal';
export { Literal, Null, Undefined } from './types/literal';
export { Never } from './types/never';
export { Number } from './types/number';
export { Object, Partial } from './types/Object';
export { Record } from './types/Record';
export { String } from './types/string';
export { Symbol } from './types/symbol';
export { Tuple } from './types/tuple';
export { Union } from './types/union';
export { Unknown } from './types/unknown';
/**
* @deprecated use Unknown
*/
export { Void } from './types/void';
export { Brand } from './types/brand';
export * from './decorator';
export { ParsedValue } from './types/ParsedValue';

@@ -1,46 +0,100 @@

import {
Result,
Union,
Union2,
Intersect,
Intersect2,
Constraint,
ConstraintCheck,
Brand,
} from './index';
import { Reflect } from './reflect';
import { Result, Union, Intersect, Constraint, ConstraintCheck, Brand, Failure } from './index';
import show from './show';
import { ValidationError } from './errors';
import { ParsedValue, ParsedValueConfig } from './types/ParsedValue';
export type InnerValidateHelper = <T>(runtype: RuntypeBase<T>, value: unknown) => Result<T>;
declare const internalSymbol: unique symbol;
const internal: typeof internalSymbol = ('__internal__' as unknown) as typeof internalSymbol;
export type ResultWithCycle<T> = (Result<T> & { cycle?: false }) | Cycle<T>;
export interface InternalValidation<TParsed> {
validate(
x: any,
innerValidate: <T>(runtype: RuntypeBase<T>, value: unknown) => Result<T>,
innerValidateToPlaceholder: <T>(runtype: RuntypeBase<T>, value: unknown) => ResultWithCycle<T>,
): ResultWithCycle<TParsed>;
test?: (
x: any,
innerValidate: <T>(runtype: RuntypeBase<T>, value: unknown) => Failure | undefined,
) => Failure | undefined;
serialize?: (
// any is used here to ensure TypeScript still treats RuntypeBase as
// covariant.
x: any,
innerSerialize: (runtype: RuntypeBase, value: unknown) => Result<any>,
innerSerializeToPlaceholder: (runtype: RuntypeBase, value: unknown) => ResultWithCycle<any>,
) => ResultWithCycle<any>;
}
/**
* A runtype determines at runtime whether a value conforms to a type specification.
*/
export interface Runtype<A = unknown> {
export interface RuntypeBase<TParsed = unknown> {
readonly tag: string;
/**
* Verifies that a value conforms to this runtype. When given a value that does
* not conform to the runtype, throws an exception.
*
* @throws ValidationError
*/
assert(x: any): asserts x is A;
assert(x: any): asserts x is TParsed;
/**
* Verifies that a value conforms to this runtype. If so, returns the same value,
* statically typed. Otherwise throws an exception.
* A type guard for this runtype.
*/
check(x: any): A;
test(x: any): x is TParsed;
/**
* Validates that a value conforms to this type, and returns a result indicating
* success or failure (does not throw).
* @deprecated use Runtype.test
*/
validate(x: any): Result<A>;
guard(x: any): x is TParsed;
/**
* A type guard for this runtype.
* Validates the value conforms to this type, and performs
* the `parse` action for any `ParsedValue` types.
*
* If the value is valid, it returns the parsed value,
* otherwise it throws a ValidationError.
*
* @throws ValidationError
*/
guard(x: any): x is A;
parse(x: any): TParsed;
/**
* @deprecated use Runtype.parse
*/
check(x: any): TParsed;
/**
* Validates the value conforms to this type, and performs
* the `parse` action for any `ParsedValue` types.
*
* Returns a `Result`, constaining the parsed value or
* error message. Does not throw!
*/
safeParse(x: any): Result<TParsed>;
/**
* @deprecated use Runtype.safeParse
*/
validate(x: any): Result<TParsed>;
show?: (ctx: {
needsParens: boolean;
parenthesize: (str: string) => string;
showChild: (rt: RuntypeBase, needsParens: boolean) => string;
}) => string;
[internal]: InternalValidation<TParsed>;
}
/**
* A runtype determines at runtime whether a value conforms to a type specification.
*/
export interface Runtype<TParsed> extends RuntypeBase<TParsed> {
/**
* Union this Runtype with another.
*/
Or<B extends Runtype>(B: B): Union2<this, B>;
Or<B extends RuntypeBase>(B: B): Union<[this, B]>;

@@ -50,3 +104,3 @@ /**

*/
And<B extends Runtype>(B: B): Intersect2<this, B>;
And<B extends RuntypeBase>(B: B): Intersect<[this, B]>;

@@ -74,7 +128,7 @@ /**

* via a type guard function. The static type of the runtype is inferred from
* the type of the guard function.
* the type of the test function.
*
* @template T - Typically inferred from the return type of the type guard
* function, so usually not needed to specify manually.
* @param {(x: Static<this>) => x is T} guard - Type guard function (see
* @param {(x: Static<this>) => x is T} test - Type test function (see
* https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)

@@ -88,3 +142,3 @@ *

withGuard<T extends Static<this>, K = unknown>(
guard: (x: Static<this>) => x is T,
test: (x: Static<this>) => x is T,
options?: { name?: string; args?: K },

@@ -99,106 +153,388 @@ ): Constraint<this, T, K>;

/**
* Convert this to a Reflect, capable of introspecting the structure of the type.
* Apply conversion functions when parsing/serializing this value
*/
reflect: Reflect;
withParser<TParsed>(value: ParsedValueConfig<this, TParsed>): ParsedValue<this, TParsed>;
}
/* @internal */ _falseWitness: A;
export interface Codec<TParsed> extends Runtype<TParsed> {
/**
* Validates the value conforms to this type, and performs
* the `serialize` action for any `ParsedValue` types.
*
* If the value is valid, and the type supports serialize,
* it returns the serialized value, otherwise it throws a
* ValidationError.
*
* @throws ValidationError
*/
serialize: (x: TParsed) => unknown;
/**
* Validates the value conforms to this type, and performs
* the `serialize` action for any `ParsedValue` types.
*
* Returns a `Result`, constaining the serialized value or
* error message. Does not throw!
*/
safeSerialize: (x: TParsed) => Result<unknown>;
}
/**
* Obtains the static type associated with a Runtype.
*/
export type Static<A extends Runtype> = A['_falseWitness'];
export type Static<A extends RuntypeBase<any>> = A extends RuntypeBase<infer T> ? T : unknown;
export function create<A extends Runtype>(
validate: (x: any, visited: VisitedState) => Result<Static<A>>,
A: any,
): A {
A.check = check;
A.assert = check;
A._innerValidate = (value: any, visited: VisitedState) => {
if (visited.has(value, A)) return { success: true, value };
return validate(value, visited);
export function create<TConfig extends Codec<any>>(
internalImplementation:
| InternalValidation<Static<TConfig>>
| InternalValidation<Static<TConfig>>['validate'],
config: Omit<
TConfig,
| 'assert'
| 'check'
| 'test'
| 'guard'
| 'parse'
| 'check'
| 'safeParse'
| 'validate'
| 'serialize'
| 'safeSerialize'
| 'Or'
| 'And'
| 'withConstraint'
| 'withGuard'
| 'withBrand'
| 'withParser'
| typeof internal
>,
): TConfig {
const A: Codec<Static<TConfig>> = {
...config,
assert,
parse,
check: parse,
safeParse,
validate: safeParse,
test,
guard: test,
serialize,
safeSerialize,
Or,
And,
withConstraint,
withGuard,
withBrand,
withParser,
toString: () => `Runtype<${show(A)}>`,
[internal]:
typeof internalImplementation === 'function'
? {
validate: internalImplementation,
}
: internalImplementation,
};
A.validate = (value: any) => A._innerValidate(value, VisitedState());
A.guard = guard;
A.Or = Or;
A.And = And;
A.withConstraint = withConstraint;
A.withGuard = withGuard;
A.withBrand = withBrand;
A.reflect = A;
A.toString = () => `Runtype<${show(A)}>`;
return A;
return (A as unknown) as TConfig;
function check(x: any) {
const validated = A.validate(x);
if (validated.success) {
return validated.value;
function safeParse(x: any) {
return innerValidate(A, x, createVisitedState());
}
function safeSerialize(x: any) {
return innerSerialize(A, x, createVisitedState());
}
function parse(x: any) {
const validated = safeParse(x);
if (!validated.success) {
throw new ValidationError(validated.message, validated.key);
}
throw new ValidationError(validated.message, validated.key);
return validated.value;
}
function serialize(x: any) {
const validated = safeSerialize(x);
if (!validated.success) {
throw new ValidationError(validated.message, validated.key);
}
return validated.value;
}
function guard(x: any): x is A {
return A.validate(x).success;
function assert(x: any): asserts x is Static<TConfig> {
const validated = innerGuard(A, x, createGuardVisitedState());
if (validated) {
throw new ValidationError(validated.message, validated.key);
}
}
function test(x: any): x is Static<TConfig> {
const validated = innerGuard(A, x, createGuardVisitedState());
return validated === undefined;
}
function Or<B extends Runtype>(B: B): Union2<A, B> {
function Or<B extends RuntypeBase>(B: B): Union<[Codec<Static<TConfig>>, B]> {
return Union(A, B);
}
function And<B extends Runtype>(B: B): Intersect2<A, B> {
function And<B extends RuntypeBase>(B: B): Intersect<[Codec<Static<TConfig>>, B]> {
return Intersect(A, B);
}
function withConstraint<T extends Static<A>, K = unknown>(
constraint: ConstraintCheck<A>,
function withConstraint<T extends Static<TConfig>, K = unknown>(
constraint: ConstraintCheck<Codec<Static<TConfig>>>,
options?: { name?: string; args?: K },
): Constraint<A, T, K> {
return Constraint<A, T, K>(A, constraint, options);
): Constraint<Codec<Static<TConfig>>, T, K> {
return Constraint<Codec<Static<TConfig>>, T, K>(A, constraint, options);
}
function withGuard<T extends Static<A>, K = unknown>(
guard: (x: Static<A>) => x is T,
function withGuard<T extends Static<TConfig>, K = unknown>(
test: (x: Static<TConfig>) => x is T,
options?: { name?: string; args?: K },
): Constraint<A, T, K> {
return Constraint<A, T, K>(A, guard, options);
): Constraint<Codec<Static<TConfig>>, T, K> {
return Constraint<Codec<Static<TConfig>>, T, K>(A, test, options);
}
function withBrand<B extends string>(B: B): Brand<B, A> {
return Brand(B, A);
function withBrand<B extends string>(B: B): Brand<B, Codec<Static<TConfig>>> {
return Brand<B, Codec<Static<TConfig>>>(B, A);
}
}
export function innerValidate<A extends Runtype>(
targetType: A,
value: any,
visited: VisitedState,
): Result<Static<A>> {
return (targetType as any)._innerValidate(value, visited);
function withParser<TParsed>(
config: ParsedValueConfig<Codec<Static<TConfig>>, TParsed>,
): ParsedValue<Codec<Static<TConfig>>, TParsed> {
return ParsedValue(A as any, config);
}
}
type VisitedState = {
has: (candidate: object, type: Runtype) => boolean;
export type Cycle<T> = {
success: true;
cycle: true;
placeholder: Partial<T>;
unwrap: () => Result<T>;
};
function VisitedState(): VisitedState {
const members: WeakMap<object, WeakMap<Runtype, true>> = new WeakMap();
const add = (candidate: object, type: Runtype) => {
if (candidate === null || !(typeof candidate === 'object')) return;
const typeSet = members.get(candidate);
members.set(
candidate,
typeSet ? typeSet.set(type, true) : (new WeakMap() as WeakMap<Runtype, true>).set(type, true),
);
function attemptMixin<T>(placeholder: any, value: T): Result<T> {
if (placeholder === value) {
return { success: true, value };
}
if (Array.isArray(placeholder) && Array.isArray(value)) {
placeholder.splice(0, placeholder.length, ...value);
return { success: true, value: placeholder as any };
}
if (
placeholder &&
typeof placeholder === 'object' &&
!Array.isArray(placeholder) &&
value &&
typeof value === 'object' &&
!Array.isArray(value)
) {
Object.assign(placeholder, value);
return { success: true, value: placeholder };
}
return {
success: false,
message: `Cannot convert a value of type "${
Array.isArray(placeholder) ? 'Array' : typeof placeholder
}" into a value of type "${
value === null ? 'null' : Array.isArray(value) ? 'Array' : typeof value
}" when it contains cycles.`,
};
}
const has = (candidate: object, type: Runtype) => {
const typeSet = members.get(candidate);
const value = (typeSet && typeSet.get(type)) || false;
add(candidate, type);
return value;
export function createValidationPlaceholder<T>(
placeholder: T,
fn: (placeholder: T) => Failure | undefined,
): Cycle<T> {
return innerMapValidationPlaceholder(
placeholder,
() => fn(placeholder) || { success: true, value: placeholder },
);
}
export function mapValidationPlaceholder<T, S>(
source: ResultWithCycle<T>,
fn: (placeholder: T) => Result<S>,
extraGuard?: RuntypeBase<S>,
): ResultWithCycle<S> {
if (!source.success) return source;
if (!source.cycle) {
const result = fn(source.value);
return (
(result.success &&
extraGuard &&
innerGuard(extraGuard, result.value, createGuardVisitedState())) ||
result
);
}
return innerMapValidationPlaceholder(
Array.isArray(source.placeholder) ? [...source.placeholder] : { ...source.placeholder },
() => source.unwrap(),
fn,
extraGuard,
);
}
function innerMapValidationPlaceholder(
placeholder: any,
populate: () => Result<any>,
fn?: (placeholder: any) => Result<any>,
extraGuard?: RuntypeBase<any>,
): Cycle<any> {
let hasCycle = false;
let cache: Result<any> | undefined;
const cycle: Cycle<any> = {
success: true,
cycle: true,
placeholder,
unwrap: () => {
if (cache) {
hasCycle = true;
return cache;
}
cache = { success: true, value: placeholder };
const sourceResult = populate();
const result = sourceResult.success && fn ? fn(sourceResult.value) : sourceResult;
if (!result.success) return result;
if (hasCycle) {
const unwrapResult = attemptMixin(cache.value, result.value);
const guardFailure =
unwrapResult.success &&
extraGuard &&
innerGuard(extraGuard, unwrapResult.value, createGuardVisitedState());
cache = guardFailure || unwrapResult;
} else {
const guardFailure =
extraGuard && innerGuard(extraGuard, result.value, createGuardVisitedState());
cache = guardFailure || result;
}
if (cache.success) {
cycle.placeholder = cache.value;
}
return cache;
},
};
return cycle;
}
return { has };
declare const OpaqueVisitedState: unique symbol;
export type OpaqueVisitedState = typeof OpaqueVisitedState;
type VisitedState = Map<RuntypeBase<unknown>, Map<any, Cycle<any>>>;
function unwrapVisitedState(o: OpaqueVisitedState): VisitedState {
return o as any;
}
function wrapVisitedState(o: VisitedState): OpaqueVisitedState {
return o as any;
}
export function createVisitedState(): OpaqueVisitedState {
return wrapVisitedState(new Map());
}
declare const OpaqueGuardVisitedState: unique symbol;
export type OpaqueGuardVisitedState = typeof OpaqueGuardVisitedState;
type GuardVisitedState = Map<RuntypeBase<unknown>, Set<any>>;
function unwrapGuardVisitedState(o: OpaqueGuardVisitedState): GuardVisitedState {
return o as any;
}
function wrapGuardVisitedState(o: GuardVisitedState): OpaqueGuardVisitedState {
return o as any;
}
export function createGuardVisitedState(): OpaqueGuardVisitedState {
return wrapGuardVisitedState(new Map());
}
export function innerValidate<T>(
targetType: RuntypeBase<T>,
value: any,
$visited: OpaqueVisitedState,
): Result<T> {
const result = innerValidateToPlaceholder(targetType, value, $visited);
if (result.cycle) {
return result.unwrap();
}
return result;
}
function innerValidateToPlaceholder<T>(
targetType: RuntypeBase<T>,
value: any,
$visited: OpaqueVisitedState,
): ResultWithCycle<T> {
const visited = unwrapVisitedState($visited);
const validator = targetType[internal];
const cached = visited.get(targetType)?.get(value);
if (cached !== undefined) {
return cached;
}
const result = validator.validate(
value,
(t, v) => innerValidate(t, v, $visited),
(t, v) => innerValidateToPlaceholder(t, v, $visited),
);
if (result.cycle) {
visited.set(targetType, (visited.get(targetType) || new Map()).set(value, result));
return result;
}
return result;
}
export function innerSerialize<T>(
targetType: RuntypeBase<T>,
value: any,
$visited: OpaqueVisitedState,
): Result<T> {
const result = innerSerializeToPlaceholder(targetType, value, $visited);
if (result.cycle) {
return result.unwrap();
}
return result;
}
function innerSerializeToPlaceholder(
targetType: RuntypeBase,
value: any,
$visited: OpaqueVisitedState,
): ResultWithCycle<any> {
const visited = unwrapVisitedState($visited);
const validator = targetType[internal];
const cached = visited.get(targetType)?.get(value);
if (cached !== undefined) {
return cached;
}
let result = (validator.serialize || validator.validate)(
value,
(t, v) => innerSerialize(t, v, $visited),
(t, v) => innerSerializeToPlaceholder(t, v, $visited),
);
if (result.cycle) {
visited.set(targetType, (visited.get(targetType) || new Map()).set(value, result));
return result;
}
return result;
}
export function innerGuard(
targetType: RuntypeBase,
value: any,
$visited: OpaqueGuardVisitedState,
): Failure | undefined {
const visited = unwrapGuardVisitedState($visited);
const validator = targetType[internal];
if (value && (typeof value === 'object' || typeof value === 'function')) {
const cached = visited.get(targetType)?.has(value);
if (cached) return undefined;
visited.set(targetType, (visited.get(targetType) || new Set()).add(value));
}
if (validator.test) {
return validator.test(value, (t, v) => innerGuard(t, v, $visited));
}
let result = validator.validate(
value,
(t, v) => innerGuard(t, v, $visited) || { success: true, value: v as any },
(t, v) => innerGuard(t, v, $visited) || { success: true, value: v as any },
);
if (result.cycle) result = result.unwrap();
if (result.success) return undefined;
else return result;
}

@@ -13,4 +13,4 @@ import {

Array,
Dictionary,
Record,
Object,
Partial,

@@ -23,9 +23,9 @@ Tuple,

InstanceOf,
Reflect,
} from '.';
import show from './show';
import { RuntypeBase } from './runtype';
class TestClass {}
const cases: [Reflect, string][] = [
const cases: [RuntypeBase, string][] = [
[Unknown, 'unknown'],

@@ -45,24 +45,24 @@ [Never, 'never'],

[Array(String).asReadonly(), 'readonly string[]'],
[Dictionary(Array(Boolean)), '{ [_: string]: boolean[] }'],
[Dictionary(Array(Boolean), 'string'), '{ [_: string]: boolean[] }'],
[Dictionary(Array(Boolean), 'number'), '{ [_: number]: boolean[] }'],
[Record({}), '{}'],
[Record({}).asReadonly(), '{}'],
[Record(String, Array(Boolean)), '{ [_: string]: boolean[] }'],
[Record(String, Array(Boolean)), '{ [_: string]: boolean[] }'],
[Record(Number, Array(Boolean)), '{ [_: number]: boolean[] }'],
[Object({}), '{}'],
[Object({}).asReadonly(), '{}'],
[Partial({}), '{}'],
[InstanceOf(TestClass), 'InstanceOf<TestClass>'],
[Array(InstanceOf(TestClass)), 'InstanceOf<TestClass>[]'],
[Record({ x: String, y: Array(Boolean) }), '{ x: string; y: boolean[]; }'],
[Record({ x: String, y: Array(Boolean) }), '{ x: string; y: boolean[]; }'],
[Record({ x: Number }).And(Partial({ y: Number })), '{ x: number; } & { y?: number; }'],
[Object({ x: String, y: Array(Boolean) }), '{ x: string; y: boolean[]; }'],
[Object({ x: String, y: Array(Boolean) }), '{ x: string; y: boolean[]; }'],
[Object({ x: Number }).And(Partial({ y: Number })), '{ x: number; } & { y?: number; }'],
[
Record({ x: String, y: Array(Boolean) }).asReadonly(),
Object({ x: String, y: Array(Boolean) }).asReadonly(),
'{ readonly x: string; readonly y: boolean[]; }',
],
[Record({ x: String, y: Array(Boolean).asReadonly() }), '{ x: string; y: readonly boolean[]; }'],
[Object({ x: String, y: Array(Boolean).asReadonly() }), '{ x: string; y: readonly boolean[]; }'],
[
Record({ x: String, y: Array(Boolean).asReadonly() }).asReadonly(),
Object({ x: String, y: Array(Boolean).asReadonly() }).asReadonly(),
'{ readonly x: string; readonly y: readonly boolean[]; }',
],
[Partial({ x: String, y: Array(Boolean) }), '{ x?: string; y?: boolean[]; }'],
[Record({ x: String, y: Array(Boolean) }).asPartial(), '{ x?: string; y?: boolean[]; }'],
[Object({ x: String, y: Array(Boolean) }).asPartial(), '{ x?: string; y?: boolean[]; }'],
[Tuple(Boolean, Number), '[boolean, number]'],

@@ -80,3 +80,3 @@ [Union(Boolean, Number), 'boolean | number'],

[Boolean.Or(Number.And(String)), 'boolean | (number & string)'],
[Boolean.Or(Record({ x: String, y: Number })), 'boolean | { x: string; y: number; }'],
[Boolean.Or(Object({ x: String, y: Number })), 'boolean | { x: string; y: number; }'],
];

@@ -83,0 +83,0 @@

@@ -1,76 +0,34 @@

import { Reflect } from './index';
import { RuntypeBase } from './runtype';
import { isLazyRuntype } from './types/lazy';
const show = (needsParens: boolean, circular: Set<Reflect>) => (refl: Reflect): string => {
const show = (needsParens: boolean, circular: Set<RuntypeBase<unknown>>) => (
runtype: RuntypeBase<unknown>,
): string => {
const parenthesize = (s: string) => (needsParens ? `(${s})` : s);
const showChild = (runtype: RuntypeBase<unknown>, needsParens: boolean) =>
show(needsParens, circular)(runtype);
if (circular.has(refl)) {
return parenthesize(`CIRCULAR ${refl.tag}`);
if (circular.has(runtype)) {
if (isLazyRuntype(runtype)) {
const underlying = runtype.underlying();
if (underlying !== runtype) {
return show(needsParens, circular)(underlying);
}
}
return parenthesize(`CIRCULAR ${runtype.tag}`);
}
circular.add(refl);
if (runtype.show) {
circular.add(runtype);
try {
switch (refl.tag) {
// Primitive types
case 'unknown':
case 'never':
case 'void':
case 'boolean':
case 'number':
case 'string':
case 'symbol':
case 'function':
return refl.tag;
// Complex types
case 'literal': {
const { value } = refl;
return typeof value === 'string' ? `"${value}"` : String(value);
}
case 'array':
return `${readonlyTag(refl)}${show(true, circular)(refl.element)}[]`;
case 'dictionary':
return `{ [_: ${refl.key}]: ${show(false, circular)(refl.value)} }`;
case 'record': {
const keys = Object.keys(refl.fields);
return keys.length
? `{ ${keys
.map(
k =>
`${readonlyTag(refl)}${k}${partialTag(refl)}: ${show(
false,
circular,
)(refl.fields[k])};`,
)
.join(' ')} }`
: '{}';
}
case 'tuple':
return `[${refl.components.map(show(false, circular)).join(', ')}]`;
case 'union':
return parenthesize(`${refl.alternatives.map(show(true, circular)).join(' | ')}`);
case 'intersect':
return parenthesize(`${refl.intersectees.map(show(true, circular)).join(' & ')}`);
case 'constraint':
return refl.name || show(needsParens, circular)(refl.underlying);
case 'instanceof':
const name = (refl.ctor as any).name;
return `InstanceOf<${name}>`;
case 'brand':
return show(needsParens, circular)(refl.entity);
try {
return runtype.show({ parenthesize, showChild, needsParens });
} finally {
circular.delete(runtype);
}
} finally {
circular.delete(refl);
}
throw Error('impossible');
return runtype.tag;
};
export default show(false, new Set<Reflect>());
function partialTag({ isPartial }: { isPartial: boolean }): string {
return isPartial ? '?' : '';
}
function readonlyTag({ isReadonly }: { isReadonly: boolean }): string {
return isReadonly ? 'readonly ' : '';
}
export default show(false, new Set<RuntypeBase>());

@@ -1,13 +0,16 @@

import { Runtype, Static, create, innerValidate } from '../runtype';
import { Static, create, RuntypeBase, Codec, createValidationPlaceholder } from '../runtype';
type ArrayStaticType<E extends Runtype, RO extends boolean> = RO extends true
? ReadonlyArray<Static<E>>
: Static<E>[];
export interface ReadonlyArray<E extends RuntypeBase<unknown> = RuntypeBase<unknown>>
extends Codec<readonly Static<E>[]> {
readonly tag: 'array';
readonly element: E;
readonly isReadonly: true;
}
interface Arr<E extends Runtype, RO extends boolean> extends Runtype<ArrayStaticType<E, RO>> {
tag: 'array';
element: E;
isReadonly: RO;
asReadonly(): Arr<E, true>;
export { Arr as Array };
interface Arr<E extends RuntypeBase<unknown> = RuntypeBase<unknown>> extends Codec<Static<E>[]> {
readonly tag: 'array';
readonly element: E;
readonly isReadonly: false;
asReadonly(): ReadonlyArray<E>;
}

@@ -18,18 +21,18 @@

*/
function InternalArr<E extends Runtype, RO extends boolean>(
element: E,
isReadonly: RO,
): Arr<E, RO> {
return withExtraModifierFuncs(
create(
(xs, visited) => {
if (!Array.isArray(xs)) {
return {
success: false,
message: `Expected array, but was ${xs === null ? xs : typeof xs}`,
};
}
function InternalArr<TElement extends RuntypeBase<unknown>, IsReadonly extends boolean>(
element: TElement,
isReadonly: IsReadonly,
): IsReadonly extends true ? ReadonlyArray<TElement> : Arr<TElement> {
const result = create<ReadonlyArray<TElement> | Arr<TElement>>(
(xs, innerValidate) => {
if (!Array.isArray(xs)) {
return {
success: false,
message: `Expected array, but was ${xs === null ? xs : typeof xs}`,
};
}
for (const x of xs) {
let validated = innerValidate(element, x, visited);
return createValidationPlaceholder([...xs], placeholder => {
for (let i = 0; i < xs.length; i++) {
const validated = innerValidate(element, xs[i]);
if (!validated.success) {

@@ -39,28 +42,35 @@ return {

message: validated.message,
key: validated.key ? `[${xs.indexOf(x)}].${validated.key}` : `[${xs.indexOf(x)}]`,
key: validated.key ? `[${i}].${validated.key}` : `[${i}]`,
};
} else {
placeholder[i] = validated.value;
}
}
return { success: true, value: xs };
});
},
{
tag: 'array',
isReadonly,
element,
show({ showChild }) {
return `${isReadonly ? 'readonly ' : ''}${showChild(element, true)}[]`;
},
{ tag: 'array', isReadonly, element },
),
},
);
if (!isReadonly) {
(result as any).asReadonly = asReadonly;
}
return result as any;
function asReadonly(): ReadonlyArray<TElement> {
return InternalArr(element, true);
}
}
function Arr<E extends Runtype, RO extends boolean>(element: E): Arr<E, false> {
function Arr<TElement extends RuntypeBase<unknown>>(element: TElement): Arr<TElement> {
return InternalArr(element, false);
}
function withExtraModifierFuncs<E extends Runtype, RO extends boolean>(A: any): Arr<E, RO> {
A.asReadonly = asReadonly;
return A;
function asReadonly(): Arr<E, true> {
return InternalArr(A.element, true);
}
export function ReadonlyArray<TElement extends RuntypeBase<unknown>>(
element: TElement,
): ReadonlyArray<TElement> {
return InternalArr(element, true);
}
export { Arr as Array };

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { create, Codec } from '../runtype';
export interface Boolean extends Runtype<boolean> {
tag: 'boolean';
export interface Boolean extends Codec<boolean> {
readonly tag: 'boolean';
}

@@ -10,3 +10,3 @@

*/
export const Boolean = create<Boolean>(
export const Boolean: Boolean = create<Boolean>(
value =>

@@ -13,0 +13,0 @@ typeof value === 'boolean'

@@ -1,7 +0,7 @@

import { Runtype, Static, create } from '../runtype';
import { RuntypeBase, Static, create, Codec } from '../runtype';
export const RuntypeName = Symbol('RuntypeName');
export interface Brand<B extends string, A extends Runtype>
extends Runtype<
export interface Brand<B extends string, A extends RuntypeBase<unknown>>
extends Codec<
Static<A> & {

@@ -11,14 +11,15 @@ [RuntypeName]: B;

> {
tag: 'brand';
brand: B;
entity: A;
readonly tag: 'brand';
readonly brand: B;
readonly entity: A;
}
export function Brand<B extends string, A extends Runtype>(brand: B, entity: A) {
export function isBrandRuntype(runtype: RuntypeBase): runtype is Brand<string, RuntypeBase> {
return 'tag' in runtype && (runtype as Brand<string, RuntypeBase>).tag === 'brand';
}
export function Brand<B extends string, A extends RuntypeBase<unknown>>(brand: B, entity: A) {
return create<Brand<B, A>>(
value => {
const validated = entity.validate(value);
return validated.success
? { success: true, value: validated.value as Static<Brand<B, A>> }
: validated;
(value, _innerValidate, innerValidateToPlaceholder) => {
return innerValidateToPlaceholder(entity, value) as any;
},

@@ -29,4 +30,7 @@ {

entity,
show({ showChild, needsParens }) {
return showChild(entity, needsParens);
},
},
);
}

@@ -1,27 +0,42 @@

import { Runtype, Static, create } from '../runtype';
import { RuntypeBase, Static, create, Codec } from '../runtype';
import { String } from './string';
import { Unknown } from './unknown';
export type ConstraintCheck<A extends Runtype> = (x: Static<A>) => boolean | string;
export type ConstraintCheck<A extends RuntypeBase<unknown>> = (x: Static<A>) => boolean | string;
export interface Constraint<A extends Runtype, T extends Static<A> = Static<A>, K = unknown>
extends Runtype<T> {
tag: 'constraint';
underlying: A;
export function isConstraintRuntype(
runtype: RuntypeBase,
): runtype is Constraint<RuntypeBase, unknown, unknown> {
return (
'tag' in runtype && (runtype as Constraint<RuntypeBase, unknown, unknown>).tag === 'constraint'
);
}
export interface Constraint<
TUnderlying extends RuntypeBase<unknown>,
TConstrained extends Static<TUnderlying> = Static<TUnderlying>,
TArgs = unknown
> extends Codec<TConstrained> {
readonly tag: 'constraint';
readonly underlying: TUnderlying;
// See: https://github.com/Microsoft/TypeScript/issues/19746 for why this isn't just
// `constraint: ConstraintCheck<A>`
constraint(x: Static<A>): boolean | string;
name?: string;
args?: K;
constraint(x: Static<TUnderlying>): boolean | string;
readonly name?: string;
readonly args?: TArgs;
}
export function Constraint<A extends Runtype, T extends Static<A> = Static<A>, K = unknown>(
underlying: A,
constraint: ConstraintCheck<A>,
options?: { name?: string; args?: K },
): Constraint<A, T, K> {
return create<Constraint<A, T, K>>(
value => {
export function Constraint<
TUnderlying extends RuntypeBase<unknown>,
TConstrained extends Static<TUnderlying> = Static<TUnderlying>,
TArgs = unknown
>(
underlying: TUnderlying,
constraint: ConstraintCheck<TUnderlying>,
options?: { name?: string; args?: TArgs },
): Constraint<TUnderlying, TConstrained, TArgs> {
return create<Constraint<TUnderlying, TConstrained, TArgs>>(
(value, innerValidate) => {
const name = options && options.name;
const validated = underlying.validate(value);
const validated = innerValidate(underlying, value);

@@ -32,6 +47,6 @@ if (!validated.success) {

const result = constraint(validated.value);
if (String.guard(result)) return { success: false, message: result };
const result = constraint(validated.value as any);
if (String.test(result)) return { success: false, message: result };
else if (!result) return { success: false, message: `Failed ${name || 'constraint'} check` };
return { success: true, value: validated.value as T };
return { success: true, value: validated.value as TConstrained };
},

@@ -44,2 +59,6 @@ {

args: options && options.args,
show({ needsParens, showChild }) {
return (options && options.name) || showChild(underlying, needsParens);
},
},

@@ -49,5 +68,7 @@ );

export interface Guard<TConstrained, TArgs = unknown>
extends Constraint<Unknown, TConstrained, TArgs> {}
export const Guard = <T, K = unknown>(
guard: (x: unknown) => x is T,
test: (x: unknown) => x is T,
options?: { name?: string; args?: K },
) => Unknown.withGuard(guard, options);
): Guard<T, K> => Unknown.withGuard(test, options);

@@ -1,69 +0,21 @@

import { Runtype, create, Static, innerValidate } from '../runtype';
import show from '../show';
import { String, Number, Record } from '..';
import { RuntypeBase } from '../runtype';
export interface StringDictionary<V extends Runtype> extends Runtype<{ [_: string]: Static<V> }> {
tag: 'dictionary';
key: 'string';
value: V;
}
export interface StringDictionary<V extends RuntypeBase> extends Record<String, V> {}
export interface NumberDictionary<V extends Runtype> extends Runtype<{ [_: number]: Static<V> }> {
tag: 'dictionary';
key: 'number';
value: V;
}
export interface NumberDictionary<V extends RuntypeBase> extends Record<Number, V> {}
/**
* Construct a runtype for arbitrary dictionaries.
* @deprecated use Record(String, value)
*/
export function Dictionary<V extends Runtype>(value: V, key?: 'string'): StringDictionary<V>;
export function Dictionary<V extends Runtype>(value: V, key?: 'number'): NumberDictionary<V>;
export function Dictionary<V extends Runtype>(value: V, key = 'string'): any {
return create<Runtype>(
(x, visited) => {
if (x === null || x === undefined) {
const a = create<any>(x as never, { tag: 'dictionary', key, value });
return { success: false, message: `Expected ${show(a)}, but was ${x}` };
}
if (typeof x !== 'object') {
const a = create<any>(x as never, { tag: 'dictionary', key, value });
return { success: false, message: `Expected ${show(a.reflect)}, but was ${typeof x}` };
}
if (Object.getPrototypeOf(x) !== Object.prototype) {
if (!Array.isArray(x)) {
const a = create<any>(x as never, { tag: 'dictionary', key, value });
return {
success: false,
message: `Expected ${show(a.reflect)}, but was ${Object.getPrototypeOf(x)}`,
};
} else if (key === 'string')
return { success: false, message: 'Expected dictionary, but was array' };
}
for (const k in x) {
// Object keys are unknown strings
if (key === 'number') {
if (isNaN(+k))
return {
success: false,
message: 'Expected dictionary key to be a number, but was string',
};
}
let validated = innerValidate(value, (x as any)[k], visited);
if (!validated.success) {
return {
success: false,
message: validated.message,
key: validated.key ? `${k}.${validated.key}` : k,
};
}
}
return { success: true, value: x };
},
{ tag: 'dictionary', key, value },
);
export function Dictionary<V extends RuntypeBase>(value: V, key?: 'string'): StringDictionary<V>;
/**
* @deprecated use Record(Number, value)
*/
export function Dictionary<V extends RuntypeBase>(value: V, key?: 'number'): NumberDictionary<V>;
export function Dictionary<V extends RuntypeBase>(
value: V,
key: 'number' | 'string' = 'string',
): Record<String | Number, V> {
return Record(key === 'number' ? Number : String, value);
}

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { create, Codec } from '../runtype';
export interface Function extends Runtype<(...args: any[]) => any> {
tag: 'function';
export interface Function extends Codec<(...args: any[]) => any> {
readonly tag: 'function';
}

@@ -10,3 +10,3 @@

*/
export const Function = create<Function>(
export const Function: Function = create<Function>(
value =>

@@ -13,0 +13,0 @@ typeof value === 'function'

@@ -1,2 +0,2 @@

import { Runtype, create } from '../runtype';
import { create, Codec } from '../runtype';

@@ -7,8 +7,8 @@ export interface Constructor<V> {

export interface InstanceOf<V> extends Runtype<V> {
tag: 'instanceof';
ctor: Constructor<V>;
export interface InstanceOf<V = unknown> extends Codec<V> {
readonly tag: 'instanceof';
readonly ctor: Constructor<V>;
}
export function InstanceOf<V>(ctor: Constructor<V>) {
export function InstanceOf<V>(ctor: Constructor<V>): InstanceOf<V> {
return create<InstanceOf<V>>(

@@ -24,4 +24,11 @@ value =>

},
{ tag: 'instanceof', ctor: ctor },
{
tag: 'instanceof',
ctor: ctor,
show() {
const name = (ctor as any).name;
return `InstanceOf<${name}>`;
},
},
);
}

@@ -1,236 +0,84 @@

import { Runtype, Static, create, innerValidate } from '../runtype';
import { Static, create, RuntypeBase, Codec, createValidationPlaceholder } from '../runtype';
import show from '../show';
export interface Intersect1<A extends Runtype> extends Runtype<Static<A>> {
tag: 'intersect';
intersectees: [A];
}
// We use the fact that a union of functions is effectively an intersection of parameters
// e.g. to safely call (({x: 1}) => void | ({y: 2}) => void) you must pass {x: 1, y: 2}
export type StaticIntersect<TIntersectees extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TIntersectees]: TIntersectees[key] extends RuntypeBase
? (parameter: Static<TIntersectees[key]>) => any
: unknown;
}[number] extends (k: infer I) => void
? I
: never;
export interface Intersect2<A extends Runtype, B extends Runtype>
extends Runtype<Static<A> & Static<B>> {
tag: 'intersect';
intersectees: [A, B];
export interface Intersect<
TIntersectees extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]
> extends Codec<StaticIntersect<TIntersectees>> {
readonly tag: 'intersect';
readonly intersectees: TIntersectees;
}
export interface Intersect3<A extends Runtype, B extends Runtype, C extends Runtype>
extends Runtype<Static<A> & Static<B> & Static<C>> {
tag: 'intersect';
intersectees: [A, B, C];
}
export interface Intersect4<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype
> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D>> {
tag: 'intersect';
intersectees: [A, B, C, D];
}
export interface Intersect5<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype
> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E>> {
tag: 'intersect';
intersectees: [A, B, C, D, E];
}
export interface Intersect6<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype
> extends Runtype<Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F>> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F];
}
export interface Intersect7<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype
>
extends Runtype<
Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G>
> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G];
}
export interface Intersect8<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype
>
extends Runtype<
Static<A> & Static<B> & Static<C> & Static<D> & Static<E> & Static<F> & Static<G> & Static<H>
> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H];
}
export interface Intersect9<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype
>
extends Runtype<
Static<A> &
Static<B> &
Static<C> &
Static<D> &
Static<E> &
Static<F> &
Static<G> &
Static<H> &
Static<I>
> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H, I];
}
export interface Intersect10<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype,
J extends Runtype
>
extends Runtype<
Static<A> &
Static<B> &
Static<C> &
Static<D> &
Static<E> &
Static<F> &
Static<G> &
Static<H> &
Static<I> &
Static<J>
> {
tag: 'intersect';
intersectees: [A, B, C, D, E, F, G, H, I, J];
}
/**
* Construct an intersection runtype from runtypes for its alternatives.
*/
export function Intersect<A extends Runtype>(A: A): Intersect1<A>;
export function Intersect<A extends Runtype, B extends Runtype>(A: A, B: B): Intersect2<A, B>;
export function Intersect<A extends Runtype, B extends Runtype, C extends Runtype>(
A: A,
B: B,
C: C,
): Intersect3<A, B, C>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype
>(A: A, B: B, C: C, D: D): Intersect4<A, B, C, D>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype
>(A: A, B: B, C: C, D: D, E: E): Intersect5<A, B, C, D, E>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F): Intersect6<A, B, C, D, E, F>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Intersect7<A, B, C, D, E, F, G>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Intersect8<A, B, C, D, E, F, G, H>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Intersect9<A, B, C, D, E, F, G, H, I>;
export function Intersect<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype,
J extends Runtype
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
): Intersect10<A, B, C, D, E, F, G, H, I, J>;
export function Intersect(...intersectees: Runtype[]): any {
return create(
(value, visited) => {
TIntersectees extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]
>(...intersectees: TIntersectees): Intersect<TIntersectees> {
return create<Intersect<TIntersectees>>(
(value, innerValidate) => {
if (Array.isArray(value)) {
return createValidationPlaceholder<any>([...value], placeholder => {
for (const targetType of intersectees) {
let validated = innerValidate(targetType, placeholder);
if (!validated.success) {
return validated;
}
if (!Array.isArray(validated.value)) {
return {
success: false,
message: `The validator ${show(
targetType,
)} attempted to convert the type of this value from an array to something else. That conversion is not valid as the child of an intersect`,
};
}
placeholder.splice(0, placeholder.length, ...validated.value);
}
});
} else if (value && typeof value === 'object') {
return createValidationPlaceholder<any>({}, placeholder => {
for (const targetType of intersectees) {
let validated = innerValidate(targetType, value);
if (!validated.success) {
return validated;
}
if (!(validated.value && typeof validated.value === 'object')) {
return {
success: false,
message: `The validator ${show(
targetType,
)} attempted to convert the type of this value from an object to something else. That conversion is not valid as the child of an intersect`,
};
}
Object.assign(placeholder, validated.value);
}
});
}
let result = value;
for (const targetType of intersectees) {
let validated = innerValidate(targetType, value, visited);
let validated = innerValidate(targetType, result);
if (!validated.success) {
return validated;
}
result = validated.value;
}
return { success: true, value };
return { success: true, value: result };
},
{ tag: 'intersect', intersectees },
{
tag: 'intersect',
intersectees,
show({ parenthesize, showChild }) {
return parenthesize(`${intersectees.map(v => showChild(v, true)).join(' & ')}`);
},
},
);
}

@@ -1,25 +0,42 @@

import { Runtype, create } from '../runtype';
import { create, RuntypeBase, Codec, Static } from '../runtype';
export interface Lazy<TUnderlying extends RuntypeBase<unknown>> extends Codec<Static<TUnderlying>> {
readonly tag: 'lazy';
readonly underlying: () => TUnderlying;
}
export function lazyValue<T>(fn: () => T) {
let value: T;
return () => {
if (!value) {
value = fn();
}
return value;
};
}
export function isLazyRuntype(runtype: RuntypeBase): runtype is Lazy<RuntypeBase> {
return 'tag' in runtype && (runtype as Lazy<RuntypeBase<unknown>>).tag === 'lazy';
}
/**
* Construct a possibly-recursive Runtype.
*/
export function Lazy<A extends Runtype>(delayed: () => A) {
const data: any = {
get tag() {
return (getWrapped() as any)['tag'];
export function Lazy<TUnderlying extends RuntypeBase<unknown>>(
delayed: () => TUnderlying,
): Lazy<TUnderlying> {
const underlying = lazyValue(delayed);
return create<Lazy<TUnderlying>>(
(value, _innerValidate, innerValidateToPlaceholder) => {
return innerValidateToPlaceholder(underlying(), value) as any;
},
};
let cached: A;
function getWrapped() {
if (!cached) {
cached = delayed();
for (const k in cached) if (k !== 'tag') data[k] = cached[k];
}
return cached;
}
return create<A>(x => {
return getWrapped().validate(x);
}, data);
{
tag: 'lazy',
underlying,
show({ showChild, needsParens }) {
return showChild(underlying(), needsParens);
},
},
);
}

@@ -1,2 +0,2 @@

import { Runtype, create } from '../runtype';
import { RuntypeBase, create, Codec } from '../runtype';

@@ -6,7 +6,8 @@ /**

*/
export type LiteralBase = undefined | null | boolean | number | string;
export type LiteralValue = undefined | null | boolean | number | string;
export interface Literal<A extends LiteralBase> extends Runtype<A> {
tag: 'literal';
value: A;
export interface Literal<TLiteralValue extends LiteralValue = LiteralValue>
extends Codec<TLiteralValue> {
readonly tag: 'literal';
readonly value: TLiteralValue;
}

@@ -21,6 +22,10 @@

export function isLiteralRuntype(runtype: RuntypeBase): runtype is Literal {
return 'tag' in runtype && (runtype as Literal).tag === 'literal';
}
/**
* Construct a runtype for a type literal.
*/
export function Literal<A extends LiteralBase>(valueBase: A): Literal<A> {
export function Literal<A extends LiteralValue>(valueBase: A): Literal<A> {
return create<Literal<A>>(

@@ -34,3 +39,9 @@ value =>

},
{ tag: 'literal', value: valueBase },
{
tag: 'literal',
value: valueBase,
show() {
return typeof valueBase === 'string' ? `"${valueBase}"` : String(valueBase);
},
},
);

@@ -37,0 +48,0 @@ }

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { Codec, create } from '../runtype';
export interface Never extends Runtype<never> {
tag: 'never';
export interface Never extends Codec<never> {
readonly tag: 'never';
}

@@ -10,3 +10,3 @@

*/
export const Never = create<Never>(
export const Never: Never = create(
value => ({

@@ -17,2 +17,2 @@ success: false,

{ tag: 'never' },
);
) as any;

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { Codec, create } from '../runtype';
export interface Number extends Runtype<number> {
tag: 'number';
export interface Number extends Codec<number> {
readonly tag: 'number';
}

@@ -10,3 +10,3 @@

*/
export const Number = create<Number>(
export const Number: Number = create<Number>(
value =>

@@ -13,0 +13,0 @@ typeof value === 'number'

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { create, Codec } from '../runtype';
export interface String extends Runtype<string> {
tag: 'string';
export interface String extends Codec<string> {
readonly tag: 'string';
}

@@ -10,3 +10,3 @@

*/
export const String = create<String>(
export const String: String = create<String>(
value =>

@@ -13,0 +13,0 @@ typeof value === 'string'

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { Codec, create } from '../runtype';
interface Sym extends Runtype<symbol> {
tag: 'symbol';
interface Sym extends Codec<symbol> {
readonly tag: 'symbol';
}

@@ -10,3 +10,3 @@

*/
const Sym = create<Sym>(
const Sym: Sym = create<Sym>(
value =>

@@ -13,0 +13,0 @@ typeof value === 'symbol'

@@ -1,233 +0,29 @@

import { Runtype, Static, create, innerValidate } from '../runtype';
import { create, RuntypeBase, Codec, createValidationPlaceholder } from '../runtype';
import { Array as Arr } from './array';
import { Unknown } from './unknown';
export interface Tuple0 extends Runtype {
tag: 'tuple';
components: [];
}
export type StaticTuple<TElements extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TElements]: TElements[key] extends RuntypeBase<infer E> ? E : unknown;
};
export interface Tuple1<A extends Runtype> extends Runtype<[Static<A>]> {
tag: 'tuple';
components: [A];
export interface Tuple<
TElements extends readonly RuntypeBase<unknown>[] = readonly RuntypeBase<unknown>[]
> extends Codec<StaticTuple<TElements>> {
readonly tag: 'tuple';
readonly components: TElements;
}
export interface Tuple2<A extends Runtype, B extends Runtype>
extends Runtype<[Static<A>, Static<B>]> {
tag: 'tuple';
components: [A, B];
export function isTupleRuntype(runtype: RuntypeBase): runtype is Tuple<readonly RuntypeBase[]> {
return 'tag' in runtype && (runtype as Tuple<readonly RuntypeBase[]>).tag === 'tuple';
}
export interface Tuple3<A extends Runtype, B extends Runtype, C extends Runtype>
extends Runtype<[Static<A>, Static<B>, Static<C>]> {
tag: 'tuple';
components: [A, B, C];
}
export interface Tuple4<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype>
extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>]> {
tag: 'tuple';
components: [A, B, C, D];
}
export interface Tuple5<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype
> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>]> {
tag: 'tuple';
components: [A, B, C, D, E];
}
export interface Tuple6<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype
> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>]> {
tag: 'tuple';
components: [A, B, C, D, E, F];
}
export interface Tuple7<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype
> extends Runtype<[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>]> {
tag: 'tuple';
components: [A, B, C, D, E, F, G];
}
export interface Tuple8<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype
>
extends Runtype<
[Static<A>, Static<B>, Static<C>, Static<D>, Static<E>, Static<F>, Static<G>, Static<H>]
> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H];
}
export interface Tuple9<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype
>
extends Runtype<
[
Static<A>,
Static<B>,
Static<C>,
Static<D>,
Static<E>,
Static<F>,
Static<G>,
Static<H>,
Static<I>,
]
> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H, I];
}
export interface Tuple10<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype,
J extends Runtype
>
extends Runtype<
[
Static<A>,
Static<B>,
Static<C>,
Static<D>,
Static<E>,
Static<F>,
Static<G>,
Static<H>,
Static<I>,
Static<J>,
]
> {
tag: 'tuple';
components: [A, B, C, D, E, F, G, H, I, J];
}
/**
* Construct a tuple runtype from runtypes for each of its elements.
*/
export function Tuple(): Tuple0;
export function Tuple<A extends Runtype>(A: A): Tuple1<A>;
export function Tuple<A extends Runtype, B extends Runtype>(A: A, B: B): Tuple2<A, B>;
export function Tuple<A extends Runtype, B extends Runtype, C extends Runtype>(
A: A,
B: B,
C: C,
): Tuple3<A, B, C>;
export function Tuple<A extends Runtype, B extends Runtype, C extends Runtype, D extends Runtype>(
A: A,
B: B,
C: C,
D: D,
): Tuple4<A, B, C, D>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype
>(A: A, B: B, C: C, D: D, E: E): Tuple5<A, B, C, D, E>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F): Tuple6<A, B, C, D, E, F>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Tuple7<A, B, C, D, E, F, G>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Tuple8<A, B, C, D, E, F, G, H>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Tuple9<A, B, C, D, E, F, G, H, I>;
export function Tuple<
A extends Runtype,
B extends Runtype,
C extends Runtype,
D extends Runtype,
E extends Runtype,
F extends Runtype,
G extends Runtype,
H extends Runtype,
I extends Runtype,
J extends Runtype
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
): Tuple10<A, B, C, D, E, F, G, H, I, J>;
export function Tuple(...components: Runtype[]): any {
return create(
(x, visited) => {
const validated = innerValidate(Arr(Unknown), x, visited);
T extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]] | readonly []
>(...components: T): Tuple<T> {
return create<Tuple<T>>(
(x, innerValidate) => {
const validated = innerValidate(Arr(Unknown), x);

@@ -249,18 +45,28 @@ if (!validated.success) {

for (let i = 0; i < components.length; i++) {
let validatedComponent = innerValidate(components[i], validated.value[i], visited);
return createValidationPlaceholder(validated.value as any, placeholder => {
for (let i = 0; i < components.length; i++) {
let validatedComponent = innerValidate(components[i], validated.value[i]);
if (!validatedComponent.success) {
return {
success: false,
message: validatedComponent.message,
key: validatedComponent.key ? `[${i}].${validatedComponent.key}` : `[${i}]`,
};
if (!validatedComponent.success) {
return {
success: false,
message: validatedComponent.message,
key: validatedComponent.key ? `[${i}].${validatedComponent.key}` : `[${i}]`,
};
}
placeholder[i] = validatedComponent.value;
}
}
return { success: true, value: x };
});
},
{ tag: 'tuple', components },
{
tag: 'tuple',
components,
show({ showChild }) {
return `[${(components as readonly RuntypeBase<unknown>[])
.map(e => showChild(e, false))
.join(', ')}]`;
},
},
);
}

@@ -1,2 +0,2 @@

import { Union, String, Literal, Record, Number, InstanceOf } from '..';
import { Union, String, Literal, Object, Number, InstanceOf, Tuple } from '..';

@@ -19,45 +19,323 @@ const ThreeOrString = Union(Literal(3), String);

it('should pick correct alternative with typescript docs example', () => {
const Square = Record({ kind: Literal('square'), size: Number });
const Rectangle = Record({ kind: Literal('rectangle'), width: Number, height: Number });
const Circle = Record({ kind: Literal('circle'), radius: Number });
const Square = Object({ kind: Literal('square'), size: Number });
const Rectangle = Object({ kind: Literal('rectangle'), width: Number, height: Number });
const Circle = Object({ kind: Literal('circle'), radius: Number });
const Shape = Union(Square, Rectangle, Circle);
expect(Shape.validate({ kind: 'square', size: new Date() })).toMatchObject({
success: false,
key: 'size',
});
expect(Shape.safeParse({ kind: 'square', size: new Date() })).toMatchInlineSnapshot(`
Object {
"key": "<kind: 'square'>.size",
"message": "Expected number, but was object",
"success": false,
}
`);
expect(Shape.validate({ kind: 'rectangle', size: new Date() })).toMatchObject({
success: false,
key: 'width',
});
expect(Shape.safeParse({ kind: 'rectangle', size: new Date() })).toMatchInlineSnapshot(`
Object {
"key": "<kind: 'rectangle'>.width",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.validate({ kind: 'circle', size: new Date() })).toMatchObject({
success: false,
key: 'radius',
});
expect(Shape.safeParse({ kind: 'circle', size: new Date() })).toMatchInlineSnapshot(`
Object {
"key": "<kind: 'circle'>.radius",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.validate({ kind: 'other', size: new Date() })).not.toHaveProperty('key');
expect(Shape.safeParse({ kind: 'other', size: new Date() })).toMatchInlineSnapshot(`
Object {
"key": "kind",
"message": "Expected 'square' | 'rectangle' | 'circle', but was 'other'",
"success": false,
}
`);
expect(Shape.safeParse(42)).toMatchInlineSnapshot(`
Object {
"message": "Expected { kind: \\"square\\"; size: number; } | { kind: \\"rectangle\\"; width: number; height: number; } | { kind: \\"circle\\"; radius: number; }, but was number",
"success": false,
}
`);
expect(Shape.safeParse(null)).toMatchInlineSnapshot(`
Object {
"message": "Expected { kind: \\"square\\"; size: number; } | { kind: \\"rectangle\\"; width: number; height: number; } | { kind: \\"circle\\"; radius: number; }, but was null",
"success": false,
}
`);
expect(Shape.safeParse({ kind: { v: 'circle' }, size: new Date() })).toMatchInlineSnapshot(`
Object {
"key": "kind",
"message": "Expected 'square' | 'rectangle' | 'circle', but was object",
"success": false,
}
`);
});
it('hould not pick alternative if the discriminant is not unique', () => {
const Square = Record({ kind: Literal('square'), size: Number });
const Rectangle = Record({ kind: Literal('rectangle'), width: Number, height: Number });
const CircularSquare = Record({ kind: Literal('square'), radius: Number });
it('should not pick alternative if the discriminant is not unique', () => {
const Square = Object({ kind: Literal('square'), size: Number });
const Rectangle = Object({ kind: Literal('rectangle'), width: Number, height: Number });
const CircularSquare = Object({ kind: Literal('square'), radius: Number });
const Shape = Union(Square, Rectangle, CircularSquare);
expect(Shape.validate({ kind: 'square', size: new Date() })).not.toHaveProperty('key');
expect(Shape.safeParse({ kind: 'square', size: new Date() })).not.toHaveProperty('key');
});
it('should not pick alternative if not all types are records', () => {
const Square = Record({ kind: Literal('square'), size: Number });
const Rectangle = Record({ kind: Literal('rectangle'), width: Number, height: Number });
const Square = Object({ kind: Literal('square'), size: Number });
const Rectangle = Object({ kind: Literal('rectangle'), width: Number, height: Number });
const Shape = Union(Square, Rectangle, InstanceOf(Date));
expect(Shape.validate({ kind: 'square', size: new Date() })).not.toHaveProperty('key');
expect(Shape.safeParse({ kind: 'square', size: new Date() })).not.toHaveProperty('key');
});
it('should handle tuples where the first component is a literal tag', () => {
const Square = Tuple(Literal('square'), Object({ size: Number }));
const Rectangle = Tuple(Literal('rectangle'), Object({ width: Number, height: Number }));
const Circle = Tuple(Literal('circle'), Object({ radius: Number }));
const Shape = Union(Square, Rectangle, Circle);
expect(Shape.safeParse(['square', { size: new Date() }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 'square'>.[1].size",
"message": "Expected number, but was object",
"success": false,
}
`);
expect(Shape.safeParse(['rectangle', { size: new Date() }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 'rectangle'>.[1].width",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.safeParse(['circle', { size: new Date() }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 'circle'>.[1].radius",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.safeParse(['other', { size: new Date() }])).toMatchInlineSnapshot(`
Object {
"key": "[0]",
"message": "Expected 'square' | 'rectangle' | 'circle', but was 'other'",
"success": false,
}
`);
});
it('hould not pick alternative if the tuple discriminant is not unique', () => {
const Square = Tuple(Literal('rectangle'), Object({ size: Number }));
const Rectangle = Tuple(Literal('rectangle'), Object({ width: Number, height: Number }));
const Circle = Tuple(Literal('circle'), Object({ radius: Number }));
const Shape = Union(Square, Rectangle, Circle);
expect(Shape.safeParse(['rectangle', { size: new Date() }])).not.toHaveProperty('key');
});
it('hould not pick alternative if the tuple has no discriminant', () => {
const Square = Tuple(String, Object({ size: Number }));
const Rectangle = Tuple(String, Object({ width: Number, height: Number }));
const Circle = Tuple(String, Object({ radius: Number }));
const Shape = Union(Square, Rectangle, Circle);
expect(Shape.safeParse(['rectangle', { size: new Date() }])).not.toHaveProperty('key');
});
it('should handle numeric tags', () => {
const Version1 = Tuple(Literal(1), Object({ size: Number }));
const Version2 = Tuple(Literal(2), Object({ width: Number, height: Number }));
const Shape = Union(Version1, Version2);
expect(Shape.safeParse([1, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
1,
Object {
"size": 10,
},
],
}
`);
expect(Shape.safeParse([2, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 2>.[1].width",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.safeParse([2, { width: 10, height: 20 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
2,
Object {
"height": 20,
"width": 10,
},
],
}
`);
expect(Shape.safeParse([3, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "[0]",
"message": "Expected 1 | 2, but was 3",
"success": false,
}
`);
const extract = Shape.match(
([_, { size }]) => ({ width: size, height: size }),
([_, dimensions]) => dimensions,
);
expect(extract([1, { size: 20 }])).toMatchInlineSnapshot(`
Object {
"height": 20,
"width": 20,
}
`);
expect(extract([2, { width: 20, height: 20 }])).toMatchInlineSnapshot(`
Object {
"height": 20,
"width": 20,
}
`);
expect(() => extract([2, { size: 20 } as any])).toThrowErrorMatchingInlineSnapshot(
`"Expected number, but was undefined in <[0]: 2>.[1].width"`,
);
});
it('should handle branded tags', () => {
const Version1 = Tuple(Literal(1).withBrand('version'), Object({ size: Number }));
const Version2 = Tuple(
Literal(2).withBrand('version'),
Object({ width: Number, height: Number }),
);
const Shape = Union(Version1, Version2);
expect(Shape.safeParse([1, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
1,
Object {
"size": 10,
},
],
}
`);
expect(Shape.safeParse([2, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 2>.[1].width",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.safeParse([2, { width: 10, height: 20 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
2,
Object {
"height": 20,
"width": 10,
},
],
}
`);
expect(Shape.safeParse([3, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "[0]",
"message": "Expected 1 | 2, but was 3",
"success": false,
}
`);
});
it('should handle constraints', () => {
const Version1 = Tuple(Literal(1).withBrand('version'), Object({ size: Number }));
const Version2 = Tuple(
Literal(2).withBrand('version'),
Object({ width: Number, height: Number }),
).withConstraint(([_, { width, height }]) =>
width > 0 && height > 0 ? true : 'Cannot have both width and height be 0',
);
const Shape = Union(Version1, Version2);
expect(Shape.safeParse([1, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
1,
Object {
"size": 10,
},
],
}
`);
expect(Shape.safeParse([2, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 2>.[1].width",
"message": "Expected number, but was undefined",
"success": false,
}
`);
expect(Shape.safeParse([2, { width: 10, height: 20 }])).toMatchInlineSnapshot(`
Object {
"success": true,
"value": Array [
2,
Object {
"height": 20,
"width": 10,
},
],
}
`);
expect(Shape.safeParse([3, { size: 10 }])).toMatchInlineSnapshot(`
Object {
"key": "[0]",
"message": "Expected 1 | 2, but was 3",
"success": false,
}
`);
expect(Shape.safeParse([2, { width: 0, height: 0 }])).toMatchInlineSnapshot(`
Object {
"key": "<[0]: 2>",
"message": "Cannot have both width and height be 0",
"success": false,
}
`);
});
});
});

@@ -1,1971 +0,253 @@

import { Runtype as Rt, Static, create, innerValidate } from '../runtype';
import {
Codec,
Static,
create,
RuntypeBase,
InnerValidateHelper,
innerValidate,
createVisitedState,
OpaqueVisitedState,
} from '../runtype';
import show from '../show';
import { LiteralBase } from './literal';
import { hasKey } from '../util';
import { LiteralValue, isLiteralRuntype } from './literal';
import { lazyValue, isLazyRuntype } from './lazy';
import { isObjectRuntype } from './Object';
import { Result } from '../result';
import { isTupleRuntype } from './tuple';
import { isBrandRuntype } from './brand';
import { isConstraintRuntype } from './constraint';
import { isParsedValueRuntype } from './ParsedValue';
import { Never } from '..';
export interface Union1<A extends Rt> extends Rt<Static<A>> {
tag: 'union';
alternatives: [A];
match: Match1<A>;
}
export type StaticUnion<TAlternatives extends readonly RuntypeBase<unknown>[]> = {
[key in keyof TAlternatives]: TAlternatives[key] extends RuntypeBase<unknown>
? Static<TAlternatives[key]>
: unknown;
}[number];
export interface Union2<A extends Rt, B extends Rt> extends Rt<Static<A> | Static<B>> {
tag: 'union';
alternatives: [A, B];
match: Match2<A, B>;
export interface Union<TAlternatives extends readonly RuntypeBase<unknown>[]>
extends Codec<StaticUnion<TAlternatives>> {
readonly tag: 'union';
readonly alternatives: TAlternatives;
match: Match<TAlternatives>;
}
export interface Union3<A extends Rt, B extends Rt, C extends Rt>
extends Rt<Static<A> | Static<B> | Static<C>> {
tag: 'union';
alternatives: [A, B, C];
match: Match3<A, B, C>;
function valueToString(value: any) {
return value === null || typeof value === 'number' || typeof value === 'boolean'
? value
: typeof value === 'string'
? `'${value}'`
: typeof value;
}
export interface Union4<A extends Rt, B extends Rt, C extends Rt, D extends Rt>
extends Rt<Static<A> | Static<B> | Static<C> | Static<D>> {
tag: 'union';
alternatives: [A, B, C, D];
match: Match4<A, B, C, D>;
}
function resolveUnderlyingType(runtype: RuntypeBase, mode: 'p' | 's' | 't'): RuntypeBase {
if (isLazyRuntype(runtype)) return resolveUnderlyingType(runtype.underlying(), mode);
if (isBrandRuntype(runtype)) return resolveUnderlyingType(runtype.entity, mode);
if (isConstraintRuntype(runtype)) return resolveUnderlyingType(runtype.underlying, mode);
if (mode === 'p' && isParsedValueRuntype(runtype))
return resolveUnderlyingType(runtype.underlying, mode);
if (mode === 't' && isParsedValueRuntype(runtype)) {
return runtype.config.test ? resolveUnderlyingType(runtype.config.test, mode) : Never;
}
if (mode === 's' && isParsedValueRuntype(runtype)) {
if (!runtype.config.serialize) {
// this node can never match
return Never;
}
return runtype.config.test ? resolveUnderlyingType(runtype.config.test, mode) : runtype;
}
export interface Union5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt>
extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E>> {
tag: 'union';
alternatives: [A, B, C, D, E];
match: Match5<A, B, C, D, E>;
return runtype;
}
export interface Union6<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt
> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F>> {
tag: 'union';
alternatives: [A, B, C, D, E, F];
match: Match6<A, B, C, D, E, F>;
}
export interface Union7<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt
> extends Rt<Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G>> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G];
match: Match7<A, B, C, D, E, F, G>;
}
export interface Union8<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt
>
extends Rt<
Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H];
match: Match8<A, B, C, D, E, F, G, H>;
}
export interface Union9<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I];
match: Match9<A, B, C, D, E, F, G, H, I>;
}
export interface Union10<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J];
match: Match10<A, B, C, D, E, F, G, H, I, J>;
}
export interface Union11<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K];
match: Match11<A, B, C, D, E, F, G, H, I, J, K>;
}
export interface Union12<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L];
match: Match12<A, B, C, D, E, F, G, H, I, J, K, L>;
}
export interface Union13<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M];
match: Match13<A, B, C, D, E, F, G, H, I, J, K, L, M>;
}
export interface Union14<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N];
match: Match14<A, B, C, D, E, F, G, H, I, J, K, L, M, N>;
}
export interface Union15<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O];
match: Match15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>;
}
export interface Union16<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P];
match: Match16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>;
}
export interface Union17<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q];
match: Match17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>;
}
export interface Union18<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R];
match: Match18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R>;
}
export interface Union19<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>
| Static<S>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S];
match: Match19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S>;
}
export interface Union20<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt,
T extends Rt
>
extends Rt<
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>
| Static<S>
| Static<T>
> {
tag: 'union';
alternatives: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T];
match: Match20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T>;
}
/**
* Construct a union runtype from runtypes for its alternatives.
*/
export function Union<A extends Rt>(A: A): Union1<A>;
export function Union<A extends Rt, B extends Rt>(A: A, B: B): Union2<A, B>;
export function Union<A extends Rt, B extends Rt, C extends Rt>(A: A, B: B, C: C): Union3<A, B, C>;
export function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt>(
A: A,
B: B,
C: C,
D: D,
): Union4<A, B, C, D>;
export function Union<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt>(
A: A,
B: B,
C: C,
D: D,
E: E,
): Union5<A, B, C, D, E>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt
>(A: A, B: B, C: C, D: D, E: E, F: F): Union6<A, B, C, D, E, F>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G): Union7<A, B, C, D, E, F, G>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H): Union8<A, B, C, D, E, F, G, H>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt
>(A: A, B: B, C: C, D: D, E: E, F: F, G: G, H: H, I: I): Union9<A, B, C, D, E, F, G, H, I>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
): Union10<A, B, C, D, E, F, G, H, I, J>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
): Union11<A, B, C, D, E, F, G, H, I, J, K>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
): Union12<A, B, C, D, E, F, G, H, I, J, K, L>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
): Union13<A, B, C, D, E, F, G, H, I, J, K, L, M>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
): Union14<A, B, C, D, E, F, G, H, I, J, K, L, M, N>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
): Union15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
P: P,
): Union16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
P: P,
Q: Q,
): Union17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
P: P,
Q: Q,
R: R,
): Union18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
P: P,
Q: Q,
R: R,
S: S,
): Union19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S>;
export function Union<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt,
T extends Rt
>(
A: A,
B: B,
C: C,
D: D,
E: E,
F: F,
G: G,
H: H,
I: I,
J: J,
K: K,
L: L,
M: M,
N: N,
O: O,
P: P,
Q: Q,
R: R,
S: S,
T: T,
): Union20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T>;
export function Union(...alternatives: Rt[]): any {
const match = (...cases: any[]) => (x: any) => {
for (let i = 0; i < alternatives.length; i++) {
if (alternatives[i].guard(x)) {
return cases[i](x);
TAlternatives extends readonly [RuntypeBase<unknown>, ...RuntypeBase<unknown>[]]
>(...alternatives: TAlternatives): Union<TAlternatives> {
type TResult = StaticUnion<TAlternatives>;
type InnerValidate = (x: any, innerValidate: InnerValidateHelper) => Result<TResult>;
function validateWithKey(
tag: string | 0,
types: Map<LiteralValue, RuntypeBase<TResult>>,
): InnerValidate {
return (value, innerValidate) => {
if (!value || typeof value !== 'object') {
return {
success: false,
message: `Expected ${show(runtype)}, but was ${value === null ? value : typeof value}`,
};
}
}
};
const validator = types.get(value[tag]);
if (validator) {
const result = innerValidate(validator, value);
if (!result.success) {
return {
success: false,
message: result.message,
key: `<${tag === 0 ? `[0]` : tag}: ${valueToString(value[tag])}>${
result.key ? `.${result.key}` : ``
}`,
};
}
return result;
} else {
return {
success: false,
message: `Expected ${Array.from(types.keys())
.map(v => (typeof v === 'string' ? `'${v}'` : v))
.join(' | ')}, but was ${valueToString(value[tag])}`,
key: tag === 0 ? `[0]` : tag,
};
}
};
}
return create(
(value, visited) => {
const commonLiteralFields: { [key: string]: LiteralBase[] } = {};
for (const alternative of alternatives) {
if (alternative.reflect.tag === 'record') {
for (const fieldName in alternative.reflect.fields) {
const field = alternative.reflect.fields[fieldName];
if (field.tag === 'literal') {
if (commonLiteralFields[fieldName]) {
if (commonLiteralFields[fieldName].every(value => value !== field.value)) {
commonLiteralFields[fieldName].push(field.value);
}
} else {
commonLiteralFields[fieldName] = [field.value];
// This must be lazy to avoid eagerly evaluating any circular references
const validatorOf = (mode: 'p' | 's' | 't'): InnerValidate => {
const excludingNever = alternatives.filter(t => resolveUnderlyingType(t, mode).tag !== 'never');
if (excludingNever.length) {
const alts = excludingNever.map(t => resolveUnderlyingType(t, mode));
const recordAlternatives = alts.filter(isObjectRuntype);
if (recordAlternatives.length === excludingNever.length) {
const commonLiteralFields: {
[key: string]: Map<LiteralValue, RuntypeBase<TResult>>;
} = {};
for (let i = 0; i < excludingNever.length; i++) {
for (const fieldName in recordAlternatives[i].fields) {
const field = resolveUnderlyingType(recordAlternatives[i].fields[fieldName], mode);
if (isLiteralRuntype(field)) {
if (!commonLiteralFields[fieldName]) {
commonLiteralFields[fieldName] = new Map();
}
if (!commonLiteralFields[fieldName].has(field.value)) {
commonLiteralFields[fieldName].set(
field.value,
// @ts-expect-error
excludingNever[i],
);
}
}
}
}
for (const tag of ['type', 'kind', 'tag', ...Object.keys(commonLiteralFields)]) {
if (
tag in commonLiteralFields &&
commonLiteralFields[tag].size === excludingNever.length
) {
return validateWithKey(tag, commonLiteralFields[tag]);
}
}
}
for (const fieldName in commonLiteralFields) {
if (commonLiteralFields[fieldName].length === alternatives.length) {
for (const alternative of alternatives) {
if (alternative.reflect.tag === 'record') {
const field = alternative.reflect.fields[fieldName];
if (
field.tag === 'literal' &&
hasKey(fieldName, value) &&
value[fieldName] === field.value
) {
return innerValidate(alternative, value, visited);
}
const tupleAlternatives = alts.filter(isTupleRuntype);
if (tupleAlternatives.length === excludingNever.length) {
const commonLiteralFields = new Map<LiteralValue, RuntypeBase<TResult>>();
for (let i = 0; i < excludingNever.length; i++) {
const field = resolveUnderlyingType(tupleAlternatives[i].components[0], mode);
if (isLiteralRuntype(field)) {
if (!commonLiteralFields.has(field.value)) {
commonLiteralFields.set(
field.value,
// @ts-expect-error
excludingNever[i],
);
}
}
}
if (commonLiteralFields.size === excludingNever.length) {
return validateWithKey(0, commonLiteralFields);
}
}
}
return (value, innerValidate) => {
let errorsWithKey = 0;
let lastError;
let lastErrorRuntype;
for (const targetType of alternatives) {
if (innerValidate(targetType, value, visited).success) {
return { success: true, value };
const result = innerValidate(targetType, value);
if (result.success) {
return result as Result<TResult>;
}
if (result.key) {
errorsWithKey++;
lastError = result;
lastErrorRuntype = targetType;
}
}
const a = create<any>(value as never, { tag: 'union', alternatives });
if (lastError && lastErrorRuntype && errorsWithKey === 1) {
return {
success: false,
message: lastError.message,
key: `<${show(lastErrorRuntype)}>.${lastError.key}`,
};
}
return {
success: false,
message: `Expected ${show(a)}, but was ${value === null ? value : typeof value}`,
message: `Expected ${show(runtype)}, but was ${value === null ? value : typeof value}`,
};
};
};
const innerValidator = lazyValue(() => ({
p: validatorOf('p'),
s: validatorOf('s'),
t: validatorOf('t'),
}));
const runtype: Union<TAlternatives> = create<Union<TAlternatives>>(
{
validate: (value, visited) => {
return innerValidator().p(value, visited);
},
serialize: (value, visited) => {
return innerValidator().s(value, visited);
},
test: (value, visited) => {
const result = innerValidator().s(
value,
(t, v) => visited(t, v) || { success: true, value: v as any },
);
return result.success ? undefined : result;
},
},
{ tag: 'union', alternatives, match },
{
tag: 'union',
alternatives,
match: match as any,
show({ parenthesize, showChild }) {
return parenthesize(`${alternatives.map(v => showChild(v, true)).join(' | ')}`);
},
},
);
}
export interface Match1<A extends Rt> {
<Z>(a: Case<A, Z>): Matcher1<A, Z>;
}
export interface Match2<A extends Rt, B extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>): Matcher2<A, B, Z>;
}
export interface Match3<A extends Rt, B extends Rt, C extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>): Matcher3<A, B, C, Z>;
}
export interface Match4<A extends Rt, B extends Rt, C extends Rt, D extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>): Matcher4<A, B, C, D, Z>;
}
export interface Match5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt> {
<Z>(a: Case<A, Z>, b: Case<B, Z>, c: Case<C, Z>, d: Case<D, Z>, e: Case<E, Z>): Matcher5<
A,
B,
C,
D,
E,
Z
>;
}
export interface Match6<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
): Matcher6<A, B, C, D, E, F, Z>;
}
export interface Match7<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
g: Case<G, Z>,
): Matcher7<A, B, C, D, E, F, G, Z>;
}
export interface Match8<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
g: Case<G, Z>,
h: Case<H, Z>,
): Matcher8<A, B, C, D, E, F, G, H, Z>;
}
export interface Match9<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
g: Case<G, Z>,
h: Case<H, Z>,
i: Case<I, Z>,
): Matcher9<A, B, C, D, E, F, G, H, I, Z>;
}
export interface Match10<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
g: Case<G, Z>,
h: Case<H, Z>,
i: Case<I, Z>,
j: Case<J, Z>,
): Matcher10<A, B, C, D, E, F, G, H, I, J, Z>;
}
export interface Match11<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt
> {
<Z>(
a: Case<A, Z>,
b: Case<B, Z>,
c: Case<C, Z>,
d: Case<D, Z>,
e: Case<E, Z>,
f: Case<F, Z>,
g: Case<G, Z>,
h: Case<H, Z>,
i: Case<I, Z>,
j: Case<J, Z>,
k: Case<K, Z>,
): Matcher11<A, B, C, D, E, F, G, H, I, J, K, Z>;
}
return runtype;
export interface Match12<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
): Matcher12<A, B, C, D, E, F, G, H, I, J, K, L, Z>;
function match(...cases: any[]) {
return (x: any) => {
const visited: OpaqueVisitedState = createVisitedState();
for (let i = 0; i < alternatives.length; i++) {
const input = innerValidate(alternatives[i], x, visited);
if (input.success) {
return cases[i](input.value);
}
}
// if none of the types matched, we should fail with an assertion error
runtype.assert(x);
};
}
}
export interface Match13<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt
> {
export interface Match<A extends readonly RuntypeBase<unknown>[]> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
): Matcher13<A, B, C, D, E, F, G, H, I, J, K, L, M, Z>;
...a: { [key in keyof A]: A[key] extends RuntypeBase<unknown> ? Case<A[key], Z> : never }
): Matcher<A, Z>;
}
export interface Match14<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
): Matcher14<A, B, C, D, E, F, G, H, I, J, K, L, M, N, Z>;
}
export type Case<T extends RuntypeBase<unknown>, Result> = (v: Static<T>) => Result;
export interface Match15<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
): Matcher15<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Z>;
}
export interface Match16<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
P: Case<P, Z>,
): Matcher16<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Z>;
}
export interface Match17<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
P: Case<P, Z>,
Q: Case<Q, Z>,
): Matcher17<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Z>;
}
export interface Match18<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
P: Case<P, Z>,
Q: Case<Q, Z>,
R: Case<R, Z>,
): Matcher18<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Z>;
}
export interface Match19<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
P: Case<P, Z>,
Q: Case<Q, Z>,
R: Case<R, Z>,
S: Case<S, Z>,
): Matcher19<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Z>;
}
export interface Match20<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt,
T extends Rt
> {
<Z>(
A: Case<A, Z>,
B: Case<B, Z>,
C: Case<C, Z>,
D: Case<D, Z>,
E: Case<E, Z>,
F: Case<F, Z>,
G: Case<G, Z>,
H: Case<H, Z>,
I: Case<I, Z>,
J: Case<J, Z>,
K: Case<K, Z>,
L: Case<L, Z>,
M: Case<M, Z>,
N: Case<N, Z>,
O: Case<O, Z>,
P: Case<P, Z>,
Q: Case<Q, Z>,
R: Case<R, Z>,
S: Case<S, Z>,
T: Case<T, Z>,
): Matcher20<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Z>;
}
export type Case<T extends Rt, Result> = (v: Static<T>) => Result;
export type Matcher1<A extends Rt, Z> = (x: Static<A>) => Z;
export type Matcher2<A extends Rt, B extends Rt, Z> = (x: Static<A> | Static<B>) => Z;
export type Matcher3<A extends Rt, B extends Rt, C extends Rt, Z> = (
x: Static<A> | Static<B> | Static<C>,
export type Matcher<A extends readonly RuntypeBase<unknown>[], Z> = (
x: {
[key in keyof A]: A[key] extends RuntypeBase<infer Type> ? Type : unknown;
}[number],
) => Z;
export type Matcher4<A extends Rt, B extends Rt, C extends Rt, D extends Rt, Z> = (
x: Static<A> | Static<B> | Static<C> | Static<D>,
) => Z;
export type Matcher5<A extends Rt, B extends Rt, C extends Rt, D extends Rt, E extends Rt, Z> = (
x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E>,
) => Z;
export type Matcher6<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
Z
> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F>) => Z;
export type Matcher7<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
Z
> = (x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G>) => Z;
export type Matcher8<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
Z
> = (
x: Static<A> | Static<B> | Static<C> | Static<D> | Static<E> | Static<F> | Static<G> | Static<H>,
) => Z;
export type Matcher9<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>,
) => Z;
export type Matcher10<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>,
) => Z;
export type Matcher11<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>,
) => Z;
export type Matcher12<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>,
) => Z;
export type Matcher13<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>,
) => Z;
export type Matcher14<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>,
) => Z;
export type Matcher15<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>,
) => Z;
export type Matcher16<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>,
) => Z;
export type Matcher17<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>,
) => Z;
export type Matcher18<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>,
) => Z;
export type Matcher19<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>
| Static<S>,
) => Z;
export type Matcher20<
A extends Rt,
B extends Rt,
C extends Rt,
D extends Rt,
E extends Rt,
F extends Rt,
G extends Rt,
H extends Rt,
I extends Rt,
J extends Rt,
K extends Rt,
L extends Rt,
M extends Rt,
N extends Rt,
O extends Rt,
P extends Rt,
Q extends Rt,
R extends Rt,
S extends Rt,
T extends Rt,
Z
> = (
x:
| Static<A>
| Static<B>
| Static<C>
| Static<D>
| Static<E>
| Static<F>
| Static<G>
| Static<H>
| Static<I>
| Static<J>
| Static<K>
| Static<L>
| Static<M>
| Static<N>
| Static<O>
| Static<P>
| Static<Q>
| Static<R>
| Static<S>
| Static<T>,
) => Z;

@@ -1,5 +0,5 @@

import { Runtype, create } from '../runtype';
import { Codec, create } from '../runtype';
export interface Unknown extends Runtype {
tag: 'unknown';
export interface Unknown extends Codec<unknown> {
readonly tag: 'unknown';
}

@@ -10,2 +10,4 @@

*/
export const Unknown = create<Unknown>(value => ({ success: true, value }), { tag: 'unknown' });
export const Unknown: Unknown = create<Unknown>(value => ({ success: true, value }), {
tag: 'unknown',
});

@@ -1,2 +0,2 @@

// Type guard to determine if an object has a given key
// Type test to determine if an object has a given key
// If this feature gets implemented, we can use `in` instead: https://github.com/Microsoft/TypeScript/issues/10485

@@ -3,0 +3,0 @@ export function hasKey<K extends string>(k: K, o: {}): o is { [_ in K]: {} } {

{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es2015", "dom"],
"isolatedModules": true,
"module": "ES2015",
"moduleResolution": "node",
"target": "ES2019",
"lib": ["es2019", "dom"],
"strict": true,

@@ -7,0 +9,0 @@ "noUnusedLocals": true,

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc