Socket
Socket
Sign inDemoInstall

io-ts

Package Overview
Dependencies
Maintainers
1
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

io-ts - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

8

CHANGELOG.md

@@ -16,6 +16,10 @@ # Changelog

# 1.1.0
# 1.1.1
* **Experimental**
* add `optional` combinator (@gcanti)
* add `clean` / `alias` functions, closes #149 (@gcanti)
* add `exact` combinator (@gcanti)
* the `strict` combinator is deprecated
* remove `optional` combinator (@gcanti)
* it doesn't play well with advanced combinators, see [here](https://github.com/gcanti/io-ts/issues/140) for a discussion

@@ -22,0 +26,0 @@ # 1.0.6

@@ -168,9 +168,3 @@ import { Either } from 'fp-ts/lib/Either';

export declare const array: <RT extends Type<any, any, mixed>>(type: RT, name?: string) => ArrayType<RT, RT["_A"][], RT["_O"][], mixed>;
export declare class OptionalType<RT extends Any, A = any, O = A, I = mixed> extends Type<A, O, I> {
readonly type: RT;
readonly _tag: 'OptionalType';
constructor(name: string, is: OptionalType<RT, A, O, I>['is'], validate: OptionalType<RT, A, O, I>['validate'], serialize: OptionalType<RT, A, O, I>['encode'], type: RT);
}
export declare const optional: <RT extends Type<any, any, mixed>>(type: RT, name?: string) => OptionalType<RT, RT["_A"] | undefined, RT["_O"] | undefined, mixed>;
export declare class InterfaceType<P extends AnyProps, A = any, O = A, I = mixed> extends Type<A, O, I> {
export declare class InterfaceType<P, A = any, O = A, I = mixed> extends Type<A, O, I> {
readonly props: P;

@@ -183,17 +177,7 @@ readonly _tag: 'InterfaceType';

}
export declare type RequiredKeys<P> = {
[K in keyof P]: P[K] extends OptionalType<any> ? never : K;
}[keyof P];
export declare type OptionalKeys<P> = {
[K in keyof P]: P[K] extends OptionalType<any> ? K : never;
}[keyof P];
export declare type TypeOfProps<P extends AnyProps> = {
[K in RequiredKeys<P>]: TypeOf<P[K]>;
} & {
[K in OptionalKeys<P>]?: TypeOf<P[K]>;
[K in keyof P]: TypeOf<P[K]>;
};
export declare type OutputOfProps<P extends AnyProps> = {
[K in RequiredKeys<P>]: OutputOf<P[K]>;
} & {
[K in OptionalKeys<P>]?: OutputOf<P[K]>;
[K in keyof P]: OutputOf<P[K]>;
};

@@ -205,3 +189,3 @@ export interface Props {

export declare const type: <P extends Props>(props: P, name?: string) => InterfaceType<P, TypeOfProps<P>, OutputOfProps<P>, mixed>;
export declare class PartialType<P extends AnyProps, A = any, O = A, I = mixed> extends Type<A, O, I> {
export declare class PartialType<P, A = any, O = A, I = mixed> extends Type<A, O, I> {
readonly props: P;

@@ -269,3 +253,3 @@ readonly _tag: 'PartialType';

export declare const readonlyArray: <RT extends Type<any, any, mixed>>(type: RT, name?: string) => ReadonlyArrayType<RT, ReadonlyArray<RT["_A"]>, ReadonlyArray<RT["_O"]>, mixed>;
export declare class StrictType<P extends AnyProps, A = any, O = A, I = mixed> extends Type<A, O, I> {
export declare class StrictType<P, A = any, O = A, I = mixed> extends Type<A, O, I> {
readonly props: P;

@@ -275,3 +259,6 @@ readonly _tag: 'StrictType';

}
/** Specifies that only the given interface properties are allowed */
/**
* Specifies that only the given properties are allowed
* @deprecated use `exact` instead
*/
export declare const strict: <P extends Props>(props: P, name?: string) => StrictType<P, TypeOfProps<P>, OutputOfProps<P>, mixed>;

@@ -288,4 +275,37 @@ export declare type TaggedProps<Tag extends string> = {

}
export declare type Tagged<Tag extends string, A = any, O = A> = InterfaceType<TaggedProps<Tag>, A, O> | StrictType<TaggedProps<Tag>, A, O> | TaggedRefinement<Tag, A, O> | TaggedUnion<Tag, A, O> | TaggedIntersection<Tag, A, O>;
export interface TaggedExact<Tag extends string> extends ExactType<Tagged<Tag>> {
}
export declare type Tagged<Tag extends string, A = any, O = A> = InterfaceType<TaggedProps<Tag>, A, O> | StrictType<TaggedProps<Tag>, A, O> | TaggedRefinement<Tag, A, O> | TaggedUnion<Tag, A, O> | TaggedIntersection<Tag, A, O> | TaggedExact<Tag>;
export declare const taggedUnion: <Tag extends string, RTS extends Tagged<Tag, any, any>[]>(tag: Tag, types: RTS, name?: string) => UnionType<RTS, RTS["_A"]["_A"], RTS["_A"]["_O"], mixed>;
export declare class ExactType<RT extends Any, A = any, O = A, I = mixed> extends Type<A, O, I> {
readonly type: RT;
readonly _tag: 'ExactType';
constructor(name: string, is: ExactType<RT, A, O, I>['is'], validate: ExactType<RT, A, O, I>['validate'], serialize: ExactType<RT, A, O, I>['encode'], type: RT);
}
export interface HasPropsRefinement extends RefinementType<HasProps, any, any, any> {
}
export interface HasPropsReadonly extends ReadonlyType<HasProps, any, any, any> {
}
export interface HasPropsIntersection extends IntersectionType<Array<HasProps>, any, any, any> {
}
export declare type HasProps = HasPropsRefinement | HasPropsReadonly | HasPropsIntersection | InterfaceType<any, any, any, any> | StrictType<any, any, any, any> | PartialType<any, any, any, any>;
export declare function exact<RT extends HasProps>(type: RT, name?: string): ExactType<RT, TypeOf<RT>, OutputOf<RT>, InputOf<RT>>;
/** Drops the runtime type "kind" */
export declare function clean<A, O = A, I = mixed>(type: Type<A, O, I>): Type<A, O, I>;
export declare type PropsOf<T extends {
props: any;
}> = T['props'];
export declare type Exact<T, X extends T> = T & {
[K in ({
[K in keyof X]: K;
} & {
[K in keyof T]: never;
} & {
[key: string]: never;
})[keyof X]]?: never;
};
/** Keeps the runtime type "kind" */
export declare function alias<A, O, P, I>(type: PartialType<P, A, O, I>): <AA extends Exact<A, AA>, OO extends Exact<O, OO> = O, PP extends Exact<P, PP> = P, II extends I = I>() => PartialType<PP, AA, OO, II>;
export declare function alias<A, O, P, I>(type: StrictType<P, A, O, I>): <AA extends Exact<A, AA>, OO extends Exact<O, OO> = O, PP extends Exact<P, PP> = P, II extends I = I>() => StrictType<PP, AA, OO, II>;
export declare function alias<A, O, P, I>(type: InterfaceType<P, A, O, I>): <AA extends Exact<A, AA>, OO extends Exact<O, OO> = O, PP extends Exact<P, PP> = P, II extends I = I>() => InterfaceType<PP, AA, OO, II>;
export { nullType as null, undefinedType as undefined, arrayType as Array, type as interface };

@@ -367,27 +367,2 @@ "use strict";

//
// optionals
//
var OptionalType = /** @class */ (function (_super) {
__extends(OptionalType, _super);
function OptionalType(name, is, validate, serialize, type) {
var _this = _super.call(this, name, is, validate, serialize) || this;
_this.type = type;
_this._tag = 'OptionalType';
return _this;
}
return OptionalType;
}(Type));
exports.OptionalType = OptionalType;
exports.optional = function (type, name) {
if (name === void 0) { name = type.name + "?"; }
return new OptionalType(name, function (m) { return undefinedType.is(m) || type.is(m); }, function (i, c) {
if (undefinedType.is(i)) {
return exports.success(i);
}
else {
return type.validate(i, c);
}
}, type.encode === exports.identity ? exports.identity : function (a) { return (undefinedType.is(a) ? a : type.encode(a)); }, type);
};
//
// interfaces

@@ -472,6 +447,3 @@ //

if (encode !== exports.identity) {
var v = encode(a[k]);
if (s[k] !== v) {
s[k] = v;
}
s[k] = encode(a[k]);
}

@@ -780,3 +752,3 @@ }

//
// strict interfaces
// strict types
//

@@ -794,25 +766,10 @@ var StrictType = /** @class */ (function (_super) {

exports.StrictType = StrictType;
/** Specifies that only the given interface properties are allowed */
/**
* Specifies that only the given properties are allowed
* @deprecated use `exact` instead
*/
exports.strict = function (props, name) {
if (name === void 0) { name = "StrictType<" + getNameFromProps(props) + ">"; }
var loose = exports.type(props);
return new StrictType(name, function (m) { return loose.is(m) && Object.getOwnPropertyNames(m).every(function (k) { return props.hasOwnProperty(k); }); }, function (m, c) {
var looseValidation = loose.validate(m, c);
if (looseValidation.isLeft()) {
return looseValidation;
}
else {
var o = looseValidation.value;
var keys = Object.getOwnPropertyNames(o);
var len = keys.length;
var errors = [];
for (var i = 0; i < len; i++) {
var key = keys[i];
if (!props.hasOwnProperty(key)) {
errors.push(exports.getValidationError(o[key], exports.appendContext(c, key, exports.never)));
}
}
return errors.length ? exports.failures(errors) : exports.success(o);
}
}, loose.encode, props);
var exactType = exact(exports.type(props));
return new StrictType(name, exactType.is, exactType.validate, exactType.encode, props);
};

@@ -862,2 +819,3 @@ var isTagged = function (tag) {

case 'RefinementType':
case 'ExactType':
return f(type.type);

@@ -921,2 +879,64 @@ }

};
//
// exact types
//
var ExactType = /** @class */ (function (_super) {
__extends(ExactType, _super);
function ExactType(name, is, validate, serialize, type) {
var _this = _super.call(this, name, is, validate, serialize) || this;
_this.type = type;
_this._tag = 'ExactType';
return _this;
}
return ExactType;
}(Type));
exports.ExactType = ExactType;
// typings-checker doesn't know Object.assign
var assign = Object.assign;
var getProps = function (type) {
switch (type._tag) {
case 'RefinementType':
case 'ReadonlyType':
return getProps(type.type);
case 'InterfaceType':
case 'StrictType':
case 'PartialType':
return type.props;
case 'IntersectionType':
return type.types.reduce(function (props, type) { return assign(props, getProps(type)); }, {});
}
};
function exact(type, name) {
if (name === void 0) { name = "ExactType<" + type.name + ">"; }
var props = getProps(type);
return new ExactType(name, function (m) { return type.is(m) && Object.getOwnPropertyNames(m).every(function (k) { return props.hasOwnProperty(k); }); }, function (m, c) {
var looseValidation = type.validate(m, c);
if (looseValidation.isLeft()) {
return looseValidation;
}
else {
var o = looseValidation.value;
var keys = Object.getOwnPropertyNames(o);
var len = keys.length;
var errors = [];
for (var i = 0; i < len; i++) {
var key = keys[i];
if (!props.hasOwnProperty(key)) {
errors.push(exports.getValidationError(o[key], exports.appendContext(c, key, exports.never)));
}
}
return errors.length ? exports.failures(errors) : exports.success(o);
}
}, type.encode, type);
}
exports.exact = exact;
/** Drops the runtime type "kind" */
function clean(type) {
return type;
}
exports.clean = clean;
function alias(type) {
return type;
}
exports.alias = alias;
//# sourceMappingURL=index.js.map
{
"name": "io-ts",
"version": "1.1.0",
"version": "1.1.1",
"description": "TypeScript compatible runtime type system for IO validation",
"files": [
"lib"
],
"files": ["lib"],
"main": "lib/index.js",

@@ -12,6 +10,9 @@ "typings": "lib/index.d.ts",

"lint": "tslint -p tsconfig.json src/**/*.ts test/**/*.ts",
"typings-checker": "typings-checker --allow-expect-error --project typings-checker/tsconfig.json typings-checker/index.ts",
"typings-checker":
"typings-checker --allow-expect-error --project typings-checker/tsconfig.json typings-checker/index.ts",
"mocha": "cross-env TS_NODE_CACHE=false TS_NODE_PROJECT=test/tsconfig.json mocha -r ts-node/register test/*.ts",
"prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"",
"fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test,examples,exercises}/**/*.ts\"",
"prettier":
"prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"",
"fix-prettier":
"prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,test,examples,exercises}/**/*.ts\"",
"test": "npm run prettier && npm run lint && npm run typings-checker && npm run mocha",

@@ -50,16 +51,4 @@ "clean": "rimraf lib/*",

},
"tags": [
"typescript",
"validation",
"inference",
"types",
"runtime"
],
"keywords": [
"typescript",
"validation",
"inference",
"types",
"runtime"
]
"tags": ["typescript", "validation", "inference", "types", "runtime"],
"keywords": ["typescript", "validation", "inference", "types", "runtime"]
}

@@ -71,6 +71,6 @@ [![build status](https://img.shields.io/travis/gcanti/io-ts/master.svg?style=flat-square)](https://travis-ci.org/gcanti/io-ts)

// ok
// validation succeeded
Person.decode(JSON.parse('{"name":"Giulio","age":43}')) // => Right({name: "Giulio", age: 43})
// ko
// validation failed
Person.decode(JSON.parse('{"name":"Giulio"}')) // => Left([...])

@@ -136,3 +136,3 @@ ```

Static types can be extracted from runtime types with the `TypeOf` operator
Static types can be extracted from runtime types using the `TypeOf` operator

@@ -155,32 +155,31 @@ ```ts

| Type | TypeScript | Flow | Runtime type / combinator |
| --------------------- | --------------------------------------- | --------------------------------------- | ------------------------------------------------------------ |
| null | `null` | `null` | `t.null` or `t.nullType` |
| undefined | `undefined` | `void` | `t.undefined` |
| string | `string` | `string` | `t.string` |
| number | `number` | `number` | `t.number` |
| boolean | `boolean` | `boolean` | `t.boolean` |
| any | `any` | `any` | `t.any` |
| never | `never` | `empty` | `t.never` |
| object | `object` | ✘ | `t.object` |
| integer | ✘ | ✘ | `t.Integer` |
| array of any | `Array<mixed>` | `Array<mixed>` | `t.Array` |
| array of type | `Array<A>` | `Array<A>` | `t.array(A)` |
| dictionary of any | `{ [key: string]: mixed }` | `{ [key: string]: mixed }` | `t.Dictionary` |
| dictionary of type | `{ [K in A]: B }` | `{ [key: A]: B }` | `t.dictionary(A, B)` |
| function | `Function` | `Function` | `t.Function` |
| literal | `'s'` | `'s'` | `t.literal('s')` |
| partial | `Partial<{ name: string }>` | `$Shape<{ name: string }>` | `t.partial({ name: t.string })` |
| optional | `name?: string` | ✘ | `name: t.optional(t.string)` |
| readonly | `Readonly<T>` | `ReadOnly<T>` | `t.readonly(T)` |
| readonly array | `ReadonlyArray<number>` | `ReadOnlyArray<number>` | `t.readonlyArray(t.number)` |
| interface | `interface A { name: string }` | `interface A { name: string }` | `t.type({ name: t.string })` or `t.type({ name: t.string })` |
| interface inheritance | `interface B extends A {}` | `interface B extends A {}` | `t.intersection([ A, t.type({}) ])` |
| tuple | `[ A, B ]` | `[ A, B ]` | `t.tuple([ A, B ])` |
| union | `A \| B` | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` |
| intersection | `A & B` | `A & B` | `t.intersection([ A, B ])` |
| keyof | `keyof M` | `$Keys<M>` | `t.keyof(M)` |
| recursive types | see [Recursive types](#recursive-types) | see [Recursive types](#recursive-types) | `t.recursion(name, definition)` |
| refinement | ✘ | ✘ | `t.refinement(A, predicate)` |
| strict/exact types | ✘ | `$Exact<{{ name: t.string }}>` | `t.strict({ name: t.string })` |
| Type | TypeScript | Runtime type / combinator |
| ------------------------- | --------------------------------------- | ----------------------------------------------------- |
| null | `null` | `t.null` or `t.nullType` |
| undefined | `undefined` | `t.undefined` |
| string | `string` | `t.string` |
| number | `number` | `t.number` |
| boolean | `boolean` | `t.boolean` |
| any | `any` | `t.any` |
| never | `never` | `t.never` |
| object | `object` | `t.object` |
| integer | ✘ | `t.Integer` |
| array of any | `Array<mixed>` | `t.Array` |
| array of type | `Array<A>` | `t.array(A)` |
| dictionary of any | `{ [key: string]: mixed }` | `t.Dictionary` |
| dictionary of type | `{ [K in A]: B }` | `t.dictionary(A, B)` |
| function | `Function` | `t.Function` |
| literal | `'s'` | `t.literal('s')` |
| partial | `Partial<{ name: string }>` | `t.partial({ name: t.string })` |
| readonly | `Readonly<T>` | `t.readonly(T)` |
| readonly array | `ReadonlyArray<number>` | `t.readonlyArray(t.number)` |
| type alias | `type A = { name: string }` | `t.type({ name: t.string })` |
| tuple | `[ A, B ]` | `t.tuple([ A, B ])` |
| union | `A \| B` | `t.union([ A, B ])` or `t.taggedUnion(tag, [ A, B ])` |
| intersection | `A & B` | `t.intersection([ A, B ])` |
| keyof | `keyof M` | `t.keyof(M)` |
| recursive types | see [Recursive types](#recursive-types) | `t.recursion(name, definition)` |
| refinement | ✘ | `t.refinement(A, predicate)` |
| exact types | ✘ | `t.exact(type)` |
| strict types (deprecated) | ✘ | `t.strict({ name: t.string })` |

@@ -236,5 +235,5 @@ # Recursive types

# Strict/Exact interfaces
# Exact types
You can make an interface strict (which means that only the given properties are allowed) using the `strict` combinator
You can make a runtime type alias exact (which means that only the given properties are allowed) using the `exact` combinator

@@ -247,30 +246,27 @@ ```ts

const StrictPerson = t.strict(Person.props)
const ExactPerson = t.exact(Person)
Person.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok
StrictPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // fails
ExactPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // fails
```
# Mixing required and optional props
# Strict types (deprecated)
**After 1.1.0**
**Note**. This combinator is deprecated, use `exact` instead.
You can mix required and optional props using the `optional` combinator
You can make a runtime type strict (which means that only the given properties are allowed) using the `strict` combinator
```ts
const A = t.type({
foo: t.string,
bar: t.optional(t.number)
const Person = t.type({
name: t.string,
age: t.number
})
type AT = t.TypeOf<typeof A>
const StrictPerson = t.strict(Person.props)
// same as
type AT = {
foo: string
bar?: number
}
Person.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // ok
StrictPerson.decode({ name: 'Giulio', age: 43, surname: 'Canti' }) // fails
```
**Before 1.1.0**
# Mixing required and optional props

@@ -299,22 +295,2 @@ You can mix required and optional props using an intersection

You can define a custom combinator to avoid the boilerplate
```ts
export function interfaceWithOptionals<RequiredProps extends t.Props, OptionalProps extends t.Props>(
required: RequiredProps,
optional: OptionalProps,
name?: string
): t.IntersectionType<
[
t.InterfaceType<RequiredProps, t.TypeOfProps<RequiredProps>>,
t.PartialType<OptionalProps, t.TypeOfPartialProps<OptionalProps>>
],
t.TypeOfProps<RequiredProps> & t.TypeOfPartialProps<OptionalProps>
> {
return t.intersection([t.interface(required), t.partial(optional)], name)
}
const C = interfaceWithOptionals({ foo: t.string }, { bar: t.number })
```
# Custom types

@@ -350,50 +326,2 @@

# Custom combinators
You can define your own combinators. Let's see some examples
## The `maybe` combinator
An equivalent to `T | null`
```ts
export function maybe<RT extends t.Any>(
type: RT,
name?: string
): t.UnionType<[RT, t.NullType], t.TypeOf<RT> | null, t.OutputOf<RT> | null, t.InputOf<RT> | null> {
return t.union<[RT, t.NullType]>([type, t.null], name)
}
```
## The `pluck` combinator
Extracting the runtime type of a field contained in each member of a union
```ts
const pluck = <F extends string, U extends t.UnionType<Array<t.InterfaceType<{ [K in F]: t.Mixed }>>>>(
union: U,
field: F
): t.Type<t.TypeOf<U>[F]> => {
return t.union(union.types.map(type => type.props[field]))
}
export const Action = t.union([
t.type({
type: t.literal('Action1'),
payload: t.type({
foo: t.string
})
}),
t.type({
type: t.literal('Action2'),
payload: t.type({
bar: t.string
})
})
])
// ActionType: t.Type<"Action1" | "Action2", "Action1" | "Action2", t.mixed>
const ActionType = pluck(Action, 'type')
```
# Tips and Tricks

@@ -451,3 +379,3 @@

Due to an upstream [bug](https://github.com/Microsoft/TypeScript/issues/14041), VS Code might display weird types for nested types
VS Code might display weird types for nested types

@@ -483,1 +411,50 @@ ```ts

```
## Solution: the `clean` and `alias` functions
The pattern
```ts
// private runtime type
const _NestedInterface = t.type({
foo: t.string,
bar: t.type({
baz: t.string
})
})
// a type alias using interface
export interface NestedInterface extends t.TypeOf<typeof _NestedInterface> {}
//
// Two possible options for the exported runtime type
//
// a clean NestedInterface which drops the kind...
export const NestedInterface = t.clean<NestedInterface, NestedInterface>(_NestedInterface)
/*
NestedInterface: t.Type<NestedInterface, NestedInterface, t.mixed>
*/
// ... or an alias of _NestedInterface which keeps the kind
export const NestedInterface = t.alias(_NestedInterface)<NestedInterface, NestedInterface>()
/*
t.InterfaceType<{
foo: t.StringType;
bar: t.InterfaceType<{
baz: t.StringType;
}, t.TypeOfProps<{
baz: t.StringType;
}>, t.OutputOfProps<{
baz: t.StringType;
}>, t.mixed>;
}, NestedInterface, NestedInterface, t.mixed>
*/
// you can also alias the props
interface NestedInterfaceProps extends t.PropsOf<typeof _NestedInterface> {}
export const NestedInterface = t.alias(_NestedInterface)<NestedInterface, NestedInterface, NestedInterfaceProps>()
/*
const NestedInterface: t.InterfaceType<NestedInterfaceProps, NestedInterface, NestedInterface, t.mixed>
*/
```

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