Comparing version 0.9.0-dev.20171123 to 0.9.0
181
CHANGELOG.md
# Changelog | ||
> **Tags:** | ||
> - [New Feature] | ||
> - [Bug Fix] | ||
> - [Breaking Change] | ||
> - [Documentation] | ||
> - [Internal] | ||
> - [Polish] | ||
> - [Experimental] | ||
> | ||
> * [New Feature] | ||
> * [Bug Fix] | ||
> * [Breaking Change] | ||
> * [Documentation] | ||
> * [Internal] | ||
> * [Polish] | ||
> * [Experimental] | ||
**Note**: Gaps between patch versions are faulty/broken releases. | ||
**Note**: A feature tagged as Experimental is in a high state of flux, you're at risk of it changing without notice. | ||
**Note**: Gaps between patch versions are faulty/broken releases. **Note**: A feature tagged as Experimental is in a | ||
high state of flux, you're at risk of it changing without notice. | ||
# 0.9.0 | ||
- **Breaking Change** | ||
- remove `t.map` and `t.mapWithName` (in general doesn't look serializable, needs more investigation) | ||
- remove `t.prism` (in general doesn't look serializable, needs more investigation) | ||
- change `Type` from interface to class (since TypeScript is structural shouldn't be a breaking change though) | ||
- remove `t._A` | ||
- add `Type#serialize` | ||
- add `Type#is` (in order to serialize unions and while we're at it, looks useful anyway) | ||
- remove `t.is` (now that there's `Type#is` is misleading) | ||
* **Breaking Change** | ||
* remove `t.map` and `t.mapWithName` (in general doesn't look serializable, needs more investigation) | ||
* remove `t.prism` (in general doesn't look serializable, needs more investigation) | ||
* change `Type` from interface to class and add `S` type parameter | ||
* remove `t._A` | ||
* add `Type#serialize` | ||
* add `Type#is` (in order to serialize unions and while we're at it, looks useful anyway) | ||
* remove `t.is` (now that there's `Type#is` is misleading) | ||
* **Experimental** | ||
* add Flowtype support (@gcanti) | ||
# 0.8.2 | ||
- **New Feature** | ||
- add `object` type, closes #86 (@gcanti) | ||
* **New Feature** | ||
* add `object` type, closes #86 (@gcanti) | ||
# 0.8.1 | ||
- **New Feature** | ||
- add `strict` combinator, closes #84 (@phiresky, @gcanti) | ||
* **New Feature** | ||
* add `strict` combinator, closes #84 (@phiresky, @gcanti) | ||
# 0.8.0 | ||
- **Breaking Change** | ||
- upgrade `fp-ts` dependency (@gcanti) | ||
* **Breaking Change** | ||
* upgrade `fp-ts` dependency (@gcanti) | ||
# 0.7.2 | ||
- **Bug Fix** | ||
- tag recursive types, fix #80 (@gcanti) | ||
* **Bug Fix** | ||
* tag recursive types, fix #80 (@gcanti) | ||
# 0.7.1 | ||
- **Bug Fix** | ||
- incorrect compile time type for dictionary, fix #75 (@gcanti) | ||
* **Bug Fix** | ||
* incorrect compile time type for dictionary, fix #75 (@gcanti) | ||
# 0.7.0 | ||
- **Breaking Change** | ||
- upgrade to latest fp-ts (0.5.1) (@gcanti) | ||
* **Breaking Change** | ||
* upgrade to latest fp-ts (0.5.1) (@gcanti) | ||
# 0.6.2 | ||
- **New Feature** | ||
- add aliases for `null` and `interface`, closes #63 (@gcanti) | ||
* **New Feature** | ||
* add aliases for `null` and `interface`, closes #63 (@gcanti) | ||
# 0.6.1 | ||
- **Internal** | ||
- handle latest fp-ts (0.4.3) (@gcanti) | ||
* **Internal** | ||
* handle latest fp-ts (0.4.3) (@gcanti) | ||
# 0.6.0 | ||
- **Breaking Change** | ||
- upgrade to latest fp-ts (0.4.0) (@gcanti) | ||
- **Internal** | ||
- allow for infinite unions (@gcanti) | ||
* **Breaking Change** | ||
* upgrade to latest fp-ts (0.4.0) (@gcanti) | ||
* **Internal** | ||
* allow for infinite unions (@gcanti) | ||
# 0.5.1 | ||
- **Bug Fix** | ||
- export and rename `interfaceType` to `_interface`, fix #57 (@gcanti) | ||
* **Bug Fix** | ||
* export and rename `interfaceType` to `_interface`, fix #57 (@gcanti) | ||
# 0.5.0 | ||
- **Breaking Change** | ||
- `Type` is now an interface | ||
- types no more own a `is` method, use `t.is` instead | ||
- unions no more own a `fold` method | ||
- `Reporter`, `PathReporter`, `ThrowReporter` are now top level modules | ||
* **Breaking Change** | ||
* `Type` is now an interface | ||
* types no more own a `is` method, use `t.is` instead | ||
* unions no more own a `fold` method | ||
* `Reporter`, `PathReporter`, `ThrowReporter` are now top level modules | ||
# 0.4.0 | ||
- **Breaking Change** | ||
- upgrade to latest `fp-ts` (`io-ts` APIs are not changed though) (@gcanti) | ||
- drop `lib-jsnext` folder | ||
* **Breaking Change** | ||
* upgrade to latest `fp-ts` (`io-ts` APIs are not changed though) (@gcanti) | ||
* drop `lib-jsnext` folder | ||
# 0.3.2 | ||
- **Bug Fix** | ||
- remove excess overloadings, fix #43 (@gcanti) | ||
* **Bug Fix** | ||
* remove excess overloadings, fix #43 (@gcanti) | ||
# 0.3.1 | ||
- **New Feature** | ||
- add mapWithName and Functor instance, fix #37 (@gcanti) | ||
- add prism combinator, fix #41 (@gcanti) | ||
* **New Feature** | ||
* add mapWithName and Functor instance, fix #37 (@gcanti) | ||
* add prism combinator, fix #41 (@gcanti) | ||
# 0.3.0 | ||
This is a breaking change *only* if you are using fp-ts APIs | ||
This is a breaking change _only_ if you are using fp-ts APIs | ||
- **Breaking Change** | ||
- upgrade to latest fp-ts v0.2 (@gcanti) | ||
* **Breaking Change** | ||
* upgrade to latest fp-ts v0.2 (@gcanti) | ||
# 0.2.3 | ||
- **Internal** | ||
- upgrade to fp-ts v0.1 (@gcanti) | ||
* **Internal** | ||
* upgrade to fp-ts v0.1 (@gcanti) | ||
# 0.2.2 | ||
- **New Feature** | ||
- add `partial` combinator (makes optional props possible) | ||
- add `readonly` combinator (values are not frozen in production) | ||
- add `readonlyArray` combinator (values are not frozen in production) | ||
- add `never` type | ||
- **Breaking Changes** | ||
- remove `maybe` combinator, can be defined in userland as | ||
* **New Feature** | ||
* add `partial` combinator (makes optional props possible) | ||
* add `readonly` combinator (values are not frozen in production) | ||
* add `readonlyArray` combinator (values are not frozen in production) | ||
* add `never` type | ||
* **Breaking Changes** | ||
* remove `maybe` combinator, can be defined in userland as | ||
```ts | ||
export function maybe<RT extends t.Any>(type: RT, name?: string): t.UnionType<[RT, typeof t.null], t.TypeOf<RT> | null> { | ||
export function maybe<RT extends t.Any>( | ||
type: RT, | ||
name?: string | ||
): t.UnionType<[RT, typeof t.null], t.TypeOf<RT> | null> { | ||
return t.union([type, t.null], name) | ||
} | ||
``` | ||
- **Polish** | ||
- export `pathReporterFailure` function from default reporters | ||
- **Bug Fix** | ||
- revert pruning excess properties (see https://github.com/gcanti/io-ts/pull/27 for context) | ||
- revert `intersection` combinator accepting only `InterfaceType`s | ||
- **Experimental** | ||
- Pattern matching / catamorphism for unions | ||
* **Polish** | ||
* export `pathReporterFailure` function from default reporters | ||
* **Bug Fix** | ||
* revert pruning excess properties (see https://github.com/gcanti/io-ts/pull/27 for context) | ||
* revert `intersection` combinator accepting only `InterfaceType`s | ||
* **Experimental** | ||
* Pattern matching / catamorphism for unions | ||
# 0.1.0 | ||
- **New Feature** | ||
- add support for jsnext | ||
- add `Integer` type | ||
* **New Feature** | ||
- **Breaking Changes** | ||
- `t.Object` type. Renamed to `t.Dictionary`, now accepts arrays so is fully equivalent to `{ [key: string]: any }`. | ||
- `t.instanceOf` combinator. Removed. | ||
- `t.object` combinator. Renamed to `t.interface`. `ObjectType` to `InterfaceType`. Excess properties are now pruned. | ||
- `mapping` combinator. Renamed to `dictionary`. `MappingType` to `DictionaryType`. | ||
- `intersection` combinator. Due to the new excess property pruning in `t.interface` now only accept `InterfaceType`s. | ||
- API `isSuccess` removed, use `either.isRight` instead | ||
- API `isFailure` removed, use `either.isLeft` instead | ||
- API `fromValidation` removed | ||
* add support for jsnext | ||
* add `Integer` type | ||
* **Breaking Changes** | ||
* `t.Object` type. Renamed to `t.Dictionary`, now accepts arrays so is fully equivalent to `{ [key: string]: any }`. | ||
* `t.instanceOf` combinator. Removed. | ||
* `t.object` combinator. Renamed to `t.interface`. `ObjectType` to `InterfaceType`. Excess properties are now pruned. | ||
* `mapping` combinator. Renamed to `dictionary`. `MappingType` to `DictionaryType`. | ||
* `intersection` combinator. Due to the new excess property pruning in `t.interface` now only accept `InterfaceType`s. | ||
* API `isSuccess` removed, use `either.isRight` instead | ||
* API `isFailure` removed, use `either.isLeft` instead | ||
* API `fromValidation` removed | ||
# 0.0.2 | ||
- **Bug Fix** | ||
- reverse overloading definitions for unions, intersections and tuples, fix inference bug | ||
* **Bug Fix** | ||
* reverse overloading definitions for unions, intersections and tuples, fix inference bug | ||
@@ -162,2 +168,1 @@ # 0.0.1 | ||
Initial release | ||
{ | ||
"name": "io-ts", | ||
"version": "0.9.0-dev.20171123", | ||
"version": "0.9.0", | ||
"description": "TypeScript compatible runtime type system for IO validation", | ||
@@ -36,3 +36,3 @@ "files": ["lib"], | ||
"dependencies": { | ||
"fp-ts": "0.6.4-dev.20171122" | ||
"fp-ts": "^0.6.4" | ||
}, | ||
@@ -39,0 +39,0 @@ "devDependencies": { |
154
README.md
@@ -37,3 +37,4 @@ # The idea | ||
Note. The `Either` type is defined in [fp-ts](https://github.com/gcanti/fp-ts), a library containing implementations of common algebraic types in TypeScript. | ||
Note. The `Either` type is defined in [fp-ts](https://github.com/gcanti/fp-ts), a library containing implementations of | ||
common algebraic types in TypeScript. | ||
@@ -86,4 +87,4 @@ **Example** | ||
- `PathReporter: Reporter<Array<string>>` | ||
- `ThrowReporter: Reporter<void>` | ||
* `PathReporter: Reporter<Array<string>>` | ||
* `ThrowReporter: Reporter<void>` | ||
@@ -96,3 +97,3 @@ Example | ||
const validation = t.validate({"name":"Giulio"}, Person) | ||
const validation = t.validate({ name: 'Giulio' }, Person) | ||
@@ -108,4 +109,5 @@ console.log(PathReporter.report(validation)) | ||
- [io-ts-reporters](https://github.com/OliverJAsh/io-ts-reporters) - Error reporters for io-ts | ||
- [geojson-iots](https://github.com/pierremarc/geojson-iots) - Runtime types for GeoJSON as defined in rfc7946 made with io-ts | ||
* [io-ts-reporters](https://github.com/OliverJAsh/io-ts-reporters) - Error reporters for io-ts | ||
* [geojson-iots](https://github.com/pierremarc/geojson-iots) - Runtime types for GeoJSON as defined in rfc7946 made with | ||
io-ts | ||
@@ -118,3 +120,4 @@ # TypeScript integration | ||
This library uses TypeScript extensively. Its API is defined in a way which automatically infers types for produced values | ||
This library uses TypeScript extensively. Its API is defined in a way which automatically infers types for produced | ||
values | ||
@@ -148,8 +151,11 @@ ![inference](docs/images/inference.png) | ||
const Category = t.recursion<ICategory>('Category', self => | ||
t.interface({ | ||
name: t.string, | ||
categories: t.array(self) | ||
}) | ||
) | ||
const Category = | ||
t.recursion < | ||
ICategory > | ||
('Category', | ||
self => | ||
t.interface({ | ||
name: t.string, | ||
categories: t.array(self) | ||
})) | ||
``` | ||
@@ -163,31 +169,31 @@ | ||
| 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<any>` | `Array<any>` | `t.Array` | | ||
| array of type | `Array<A>` | `Array<A>` | `t.array(A)` | | ||
| dictionary of any | `{ [key: string]: any }` | `{ [key: string]: any }` | `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 })` | | ||
| 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.interface({ name: t.string })` or `t.type({ name: t.string })` | | ||
| interface inheritance | `interface B extends A {}` | `interface B extends A {}` | `t.intersection([ A, t.interface({}) ])` | | ||
| tuple | `[ A, B ]` | `[ A, B ]` | `t.tuple([ A, B ])` | | ||
| union | `A \| B` | `A \| B` | `t.union([ 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 | 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<any>` | `Array<any>` | `t.Array` | | ||
| array of type | `Array<A>` | `Array<A>` | `t.array(A)` | | ||
| dictionary of any | `{ [key: string]: any }` | `{ [key: string]: any }` | `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 })` | | ||
| 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.interface({ name: t.string })` or `t.type({ name: t.string })` | | ||
| interface inheritance | `interface B extends A {}` | `interface B extends A {}` | `t.intersection([ A, t.interface({}) ])` | | ||
| tuple | `[ A, B ]` | `[ A, B ]` | `t.tuple([ A, B ])` | | ||
| union | `A \| B` | `A \| B` | `t.union([ 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 })` | | ||
@@ -239,3 +245,3 @@ # Refinements | ||
type CT = { | ||
foo: string, | ||
foo: string | ||
bar?: number | ||
@@ -284,3 +290,3 @@ } | ||
```ts | ||
export function maybe<RT extends t.Any>(type: RT, name?: string): t.UnionType<[RT, t.NullType]> { | ||
export function maybe<RT extends t.Any>(type: RT, name?: string): t.UnionType<[RT, t.NullType], t.TypeOf<RT> | null> { | ||
return t.union<[RT, t.NullType]>([type, t.null], name) | ||
@@ -290,53 +296,2 @@ } | ||
## The `brand` combinator | ||
The problem | ||
```ts | ||
const payload = { | ||
celsius: 100, | ||
fahrenheit: 100 | ||
} | ||
const Payload = t.interface({ | ||
celsius: t.number, | ||
fahrenheit: t.number | ||
}) | ||
// x can be anything | ||
function naiveConvertFtoC(x: number): number { | ||
return (x - 32) / 1.8; | ||
} | ||
// typo: celsius instead of fahrenheit | ||
console.log(t.validate(payload, Payload).map(x => naiveConvertFtoC(x.celsius))) // NO error :( | ||
``` | ||
Solution (branded types) | ||
```ts | ||
export function brand<S, A, B extends string>(type: t.Type<S, A>, _: B): t.Type<S, A & { readonly __brand: B }> { | ||
return type as any | ||
} | ||
const Fahrenheit = brand(t.number, 'Fahrenheit') | ||
const Celsius = brand(t.number, 'Celsius') | ||
type CelsiusT = t.TypeOf<typeof Celsius> | ||
type FahrenheitT = t.TypeOf<typeof Fahrenheit> | ||
const Payload2 = t.interface({ | ||
celsius: Celsius, | ||
fahrenheit: Fahrenheit | ||
}) | ||
// narrowed types | ||
function convertFtoC(fahrenheit: FahrenheitT): CelsiusT { | ||
return ((fahrenheit - 32) / 1.8) as CelsiusT | ||
} | ||
console.log(t.validate(payload, Payload2).map(x => convertFtoC(x.celsius))) // error: Type '"Celsius"' is not assignable to type '"Fahrenheit"' | ||
console.log(t.validate(payload, Payload2).map(x => convertFtoC(x.fahrenheit))) // ok | ||
``` | ||
# Recipes | ||
@@ -346,3 +301,3 @@ | ||
No, however you can define your own logic for that (if you *really* trust the input) | ||
No, however you can define your own logic for that (if you _really_ trust the input) | ||
@@ -366,3 +321,4 @@ ```ts | ||
Due to an upstream [bug](https://github.com/Microsoft/TypeScript/issues/14041), VS Code might display weird types for nested interfaces | ||
Due to an upstream [bug](https://github.com/Microsoft/TypeScript/issues/14041), VS Code might display weird types for | ||
nested interfaces | ||
@@ -374,5 +330,5 @@ ```ts | ||
}) | ||
}); | ||
}) | ||
type NestedInterfaceType = t.TypeOf<typeof NestedInterface>; | ||
type NestedInterfaceType = t.TypeOf<typeof NestedInterface> | ||
/* | ||
@@ -379,0 +335,0 @@ Hover on NestedInterfaceType will display |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
98868
339
+ Addedfp-ts@0.6.8(transitive)
- Removedfp-ts@0.6.4-dev.20171122(transitive)
Updatedfp-ts@^0.6.4