Skip to content

Commit

Permalink
add lensesFromTuple and prismsFromUnion (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Sep 21, 2017
1 parent 66aeeec commit b0791eb
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 6 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
**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.0.1
# 0.0.2

- **New Feature**
- add `lensesFromInterface` (@leemhenson)
- add `lensesFromTuple` (@gcanti)
- add `prismsFromUnion` (@gcanti)

# 0.0.1

Initial release
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "io-ts-types",
"version": "0.0.1",
"version": "0.0.2",
"description": "A collection of runtime types for use with io-ts",
"files": ["lib"],
"main": "lib/index.js",
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export { AnyStringPrism } from './monocle-ts/AnyStringPrism'
export { composeTypeWithPrism } from './monocle-ts/composeTypeWithPrism'
export { createRangePrism } from './monocle-ts/createRangePrism'
export { ISOStringDatePrism } from './monocle-ts/ISOStringDatePrism'
export { lensesFromProps } from './monocle-ts/lensesFromProps'
export { lensesFromInterface } from './monocle-ts/lensesFromInterface'
export { lensesFromTuple } from './monocle-ts/lensesFromTuple'
export { NumberDatePrism } from './monocle-ts/NumberDatePrism'
export { NumberIntegerPrism } from './monocle-ts/NumberIntegerPrism'
export { prismsFromUnion } from './monocle-ts/prismsFromUnion'
export { StringJSONPrism } from './monocle-ts/StringJSONPrism'
export { StringNumberPrism } from './monocle-ts/StringNumberPrism'
import * as TypePrismIso from './monocle-ts/TypePrismIso'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type LensesFromProps<P extends t.Props, T extends t.InterfaceOf<P> = t.In
[K in keyof P]: Lens<T, T[K]>
}

export function lensesFromProps<P extends t.Props>(i: t.InterfaceType<P>): LensesFromProps<P> {
export function lensesFromInterface<P extends t.Props>(i: t.InterfaceType<P>): LensesFromProps<P> {
const r: any = {}
for (const k in i.props) {
r[k] = Lens.fromProp<any, typeof k>(k)
Expand Down
50 changes: 50 additions & 0 deletions src/monocle-ts/lensesFromTuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as t from 'io-ts'
import { Lens } from 'monocle-ts'

export type LensesFromTuple5<T extends t.TupleType<[t.Any, t.Any, t.Any, t.Any, t.Any], any>> = {
'L0': Lens<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'L1': Lens<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'L2': Lens<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
'L3': Lens<t.TypeOf<T>, t.TypeOf<T['types']['3']>>
'L4': Lens<t.TypeOf<T>, t.TypeOf<T['types']['4']>>
}
export type LensesFromTuple4<T extends t.TupleType<[t.Any, t.Any, t.Any, t.Any], any>> = {
'L0': Lens<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'L1': Lens<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'L2': Lens<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
'L3': Lens<t.TypeOf<T>, t.TypeOf<T['types']['3']>>
}
export type LensesFromTuple3<T extends t.TupleType<[t.Any, t.Any, t.Any], any>> = {
'L0': Lens<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'L1': Lens<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'L2': Lens<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
}
export type LensesFromTuple2<T extends t.TupleType<[t.Any, t.Any], any>> = {
'L0': Lens<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'L1': Lens<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
}
export type LensesFromTuple1<T extends t.TupleType<[t.Any], any>> = {
'L0': Lens<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
}

export function lensesFromTuple<T extends t.TupleType<[t.Any, t.Any, t.Any, t.Any, t.Any], any>>(
type: T
): LensesFromTuple5<T>
export function lensesFromTuple<T extends t.TupleType<[t.Any, t.Any, t.Any, t.Any], any>>(type: T): LensesFromTuple4<T>
export function lensesFromTuple<T extends t.TupleType<[t.Any, t.Any, t.Any], any>>(type: T): LensesFromTuple3<T>
export function lensesFromTuple<T extends t.TupleType<[t.Any, t.Any], any>>(type: T): LensesFromTuple2<T>
export function lensesFromTuple<T extends t.TupleType<[t.Any], any>>(type: T): LensesFromTuple1<T>
export function lensesFromTuple<T extends t.TupleType<any, any>>(type: T): { [key: string]: Lens<any, any> } {
const r: { [key: string]: Lens<any, any> } = {}
for (let i = 0; i < type.types.length; i++) {
r['L' + i] = new Lens(
s => s[i],
a => s => {
const s2 = s.slice()
s2[i] = a
return s2
}
)
}
return r
}
39 changes: 39 additions & 0 deletions src/monocle-ts/prismsFromUnion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as t from 'io-ts'
import { Prism } from 'monocle-ts'

export type PrismsFromUnion5<T extends t.UnionType<[t.Any, t.Any, t.Any, t.Any, t.Any]>> = {
'P0': Prism<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'P1': Prism<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'P2': Prism<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
'P3': Prism<t.TypeOf<T>, t.TypeOf<T['types']['3']>>
'P4': Prism<t.TypeOf<T>, t.TypeOf<T['types']['4']>>
}
export type PrismsFromUnion4<T extends t.UnionType<[t.Any, t.Any, t.Any, t.Any]>> = {
'P0': Prism<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'P1': Prism<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'P2': Prism<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
'P3': Prism<t.TypeOf<T>, t.TypeOf<T['types']['3']>>
}
export type PrismsFromUnion3<T extends t.UnionType<[t.Any, t.Any, t.Any]>> = {
'P0': Prism<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'P1': Prism<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
'P2': Prism<t.TypeOf<T>, t.TypeOf<T['types']['2']>>
}
export type PrismsFromUnion2<T extends t.UnionType<[t.Any, t.Any]>> = {
'P0': Prism<t.TypeOf<T>, t.TypeOf<T['types']['0']>>
'P1': Prism<t.TypeOf<T>, t.TypeOf<T['types']['1']>>
}

export function prismsFromUnion<T extends t.UnionType<[t.Any, t.Any, t.Any, t.Any, t.Any]>>(
type: T
): PrismsFromUnion5<T>
export function prismsFromUnion<T extends t.UnionType<[t.Any, t.Any, t.Any, t.Any]>>(type: T): PrismsFromUnion4<T>
export function prismsFromUnion<T extends t.UnionType<[t.Any, t.Any, t.Any]>>(type: T): PrismsFromUnion3<T>
export function prismsFromUnion<T extends t.UnionType<[t.Any, t.Any]>>(type: T): PrismsFromUnion2<T>
export function prismsFromUnion<T extends t.UnionType<any>>(type: T): { [key: string]: Prism<any, any> } {
const r: { [key: string]: Prism<any, any> } = {}
for (let i = 0; i < type.types.length; i++) {
r['P' + i] = new Prism(s => t.validate(s, type.types[i]).toOption(), a => a)
}
return r
}
32 changes: 30 additions & 2 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import {
StringNumberPrism,
StringJSONPrism,
DateFromNumber,
JSONFromString
JSONFromString,
lensesFromInterface,
lensesFromTuple,
prismsFromUnion
} from '../src'
import * as t from 'io-ts'
import { None, Some } from 'fp-ts/lib/Option'
import { None, Some, none, some } from 'fp-ts/lib/Option'
import { Left, Right } from 'fp-ts/lib/Either'
import { fromSome, fromRight } from './helpers'

Expand Down Expand Up @@ -110,6 +113,31 @@ describe('monocle-ts', () => {
assert.strictEqual(fromSome(P.getOption('null')), null)
assert.deepEqual(fromSome(P.getOption('{"name":"Giulio"}')), { name: 'Giulio' })
})

it('lensesFromInterface', () => {
const Person = t.interface({
name: t.string,
age: t.number
})
const lenses = lensesFromInterface(Person)
assert.strictEqual(lenses.age.get({ name: 'Giulio', age: 43 }), 43)
})

it('lensesFromTuple', () => {
const Point = t.tuple([t.number, t.number])
const pointLenses = lensesFromTuple(Point)
assert.strictEqual(pointLenses.L1.get([100, 200]), 200)
assert.deepEqual(pointLenses.L0.set(50)([100, 200]), [50, 200])
})

it('prismsFromUnion', () => {
const RuntimeUnion = t.union([t.string, t.number])
const unionPrisms = prismsFromUnion(RuntimeUnion)
assert.deepEqual(unionPrisms.P0.getOption('a'), some('a'))
assert.deepEqual(unionPrisms.P0.getOption(1), none)
assert.deepEqual(unionPrisms.P1.getOption('a'), none)
assert.deepEqual(unionPrisms.P1.getOption(1), some(1))
})
})

describe('JSON', () => {
Expand Down

0 comments on commit b0791eb

Please sign in to comment.