diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d952fe..cbcd82d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/package.json b/package.json index 82db6da..4d09f38 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/index.ts b/src/index.ts index c38c287..0bc9e39 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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' diff --git a/src/monocle-ts/lensesFromProps.ts b/src/monocle-ts/lensesFromInterface.ts similarity index 75% rename from src/monocle-ts/lensesFromProps.ts rename to src/monocle-ts/lensesFromInterface.ts index 0fc9faf..2d6ff80 100644 --- a/src/monocle-ts/lensesFromProps.ts +++ b/src/monocle-ts/lensesFromInterface.ts @@ -5,7 +5,7 @@ export type LensesFromProps

= t.In [K in keyof P]: Lens } -export function lensesFromProps

(i: t.InterfaceType

): LensesFromProps

{ +export function lensesFromInterface

(i: t.InterfaceType

): LensesFromProps

{ const r: any = {} for (const k in i.props) { r[k] = Lens.fromProp(k) diff --git a/src/monocle-ts/lensesFromTuple.ts b/src/monocle-ts/lensesFromTuple.ts new file mode 100644 index 0000000..6adedce --- /dev/null +++ b/src/monocle-ts/lensesFromTuple.ts @@ -0,0 +1,50 @@ +import * as t from 'io-ts' +import { Lens } from 'monocle-ts' + +export type LensesFromTuple5> = { + 'L0': Lens, t.TypeOf> + 'L1': Lens, t.TypeOf> + 'L2': Lens, t.TypeOf> + 'L3': Lens, t.TypeOf> + 'L4': Lens, t.TypeOf> +} +export type LensesFromTuple4> = { + 'L0': Lens, t.TypeOf> + 'L1': Lens, t.TypeOf> + 'L2': Lens, t.TypeOf> + 'L3': Lens, t.TypeOf> +} +export type LensesFromTuple3> = { + 'L0': Lens, t.TypeOf> + 'L1': Lens, t.TypeOf> + 'L2': Lens, t.TypeOf> +} +export type LensesFromTuple2> = { + 'L0': Lens, t.TypeOf> + 'L1': Lens, t.TypeOf> +} +export type LensesFromTuple1> = { + 'L0': Lens, t.TypeOf> +} + +export function lensesFromTuple>( + type: T +): LensesFromTuple5 +export function lensesFromTuple>(type: T): LensesFromTuple4 +export function lensesFromTuple>(type: T): LensesFromTuple3 +export function lensesFromTuple>(type: T): LensesFromTuple2 +export function lensesFromTuple>(type: T): LensesFromTuple1 +export function lensesFromTuple>(type: T): { [key: string]: Lens } { + const r: { [key: string]: Lens } = {} + 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 +} diff --git a/src/monocle-ts/prismsFromUnion.ts b/src/monocle-ts/prismsFromUnion.ts new file mode 100644 index 0000000..20635d1 --- /dev/null +++ b/src/monocle-ts/prismsFromUnion.ts @@ -0,0 +1,39 @@ +import * as t from 'io-ts' +import { Prism } from 'monocle-ts' + +export type PrismsFromUnion5> = { + 'P0': Prism, t.TypeOf> + 'P1': Prism, t.TypeOf> + 'P2': Prism, t.TypeOf> + 'P3': Prism, t.TypeOf> + 'P4': Prism, t.TypeOf> +} +export type PrismsFromUnion4> = { + 'P0': Prism, t.TypeOf> + 'P1': Prism, t.TypeOf> + 'P2': Prism, t.TypeOf> + 'P3': Prism, t.TypeOf> +} +export type PrismsFromUnion3> = { + 'P0': Prism, t.TypeOf> + 'P1': Prism, t.TypeOf> + 'P2': Prism, t.TypeOf> +} +export type PrismsFromUnion2> = { + 'P0': Prism, t.TypeOf> + 'P1': Prism, t.TypeOf> +} + +export function prismsFromUnion>( + type: T +): PrismsFromUnion5 +export function prismsFromUnion>(type: T): PrismsFromUnion4 +export function prismsFromUnion>(type: T): PrismsFromUnion3 +export function prismsFromUnion>(type: T): PrismsFromUnion2 +export function prismsFromUnion>(type: T): { [key: string]: Prism } { + const r: { [key: string]: Prism } = {} + 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 +} diff --git a/test/index.ts b/test/index.ts index b2eb3d4..47109a9 100644 --- a/test/index.ts +++ b/test/index.ts @@ -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' @@ -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', () => {