gcanti / io-ts-types

A collection of codecs and combinators for use with io-ts
https://gcanti.github.io/io-ts-types/
MIT License
311 stars 40 forks source link

added alt function #120

Closed mohaalak closed 4 years ago

mohaalak commented 4 years ago

I wrote a function named alt this function will accept two codecs, both of them should have the same output type, but their input type can be different

Alternative codec for the same output, the encoder will be the first parameter that provided to alt this function is good when you know that you want some type but the input can be in multiple forms

import { NumberFromString } from 'io-ts-types/lib/NumberFromString'
import { DateFromISOString } from 'io-ts-types/lib/DateFromISOString'
import {date} from 'io-ts-types/lib/date'
import { right } from 'fp-ts/lib/Either'
import { alt } from 'io-ts-types/lib/alt'
import * as t from 'io-ts'
import { PathReporter } from 'io-ts/lib/PathReporter'
const T = alt(t.number, NumberFromString)

assert.deepStrictEqual(T.decode('1'), right(1))
assert.deepStrictEqual(T.decode(1), right(1))
assert.deepStrictEqual(PathReporter.report(T.decode('a')), ['Invalid value "a" supplied to : alt(number, NumberFromString)'])

// encoder will always be the first one
const D = alt(DateFromISOString, date)

// type A = t.TypeOf<typeof D> // Date
// type O = t.OutputOf<typeof D> // string

const d = new Date(Date.UTC(1988, 10, 10, 0, 0, 0))
assert.strictEqual(D.encode(d), '1988-11-10T00:00:00.000Z')
gcanti commented 4 years ago

@mohaalak is there a difference from union?

import * as assert from 'assert'
import { right } from 'fp-ts/lib/Either'
import * as t from 'io-ts'
import { date } from 'io-ts-types/lib/date'
import { DateFromISOString } from 'io-ts-types/lib/DateFromISOString'
import { NumberFromString } from 'io-ts-types/lib/NumberFromString'
import { PathReporter } from 'io-ts/lib/PathReporter'

const T1 = t.union([t.number, NumberFromString])
assert.deepStrictEqual(T1.decode('2'), right(2))
assert.deepStrictEqual(T1.decode(2), right(2))

const T2 = t.union([t.number, NumberFromString])
assert.deepStrictEqual(PathReporter.report(T2.decode('a')), [
  'Invalid value "a" supplied to : (number | NumberFromString)/0: number',
  'Invalid value "a" supplied to : (number | NumberFromString)/1: NumberFromString'
])

const T3 = t.union([DateFromISOString, date])
const d = new Date(Date.UTC(1988, 10, 10, 0, 0, 0))
assert.strictEqual(T3.encode(d), '1988-11-10T00:00:00.000Z')
mohaalak commented 4 years ago

I think it's nearly identical just the encode function will return the first codec provided in the array but the return type is both of them, but that is a small issue, so I close this pull request