0

I've come across certain challenge with Either.DO

Here's a working example

import * as A from 'fp-ts/Apply'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
import * as S from 'fp-ts/Semigroup'
import * as string from 'fp-ts/string'
import * as RR from 'fp-ts/ReadonlyRecord';

const parseString = (u: unknown): E.Either<string, string> =>
  typeof u === 'string' ? E.right(u) : E.left('not a string')

const parseNumber = (u: unknown): E.Either<string, number> =>
  typeof u === 'number' ? E.right(u) : E.left('not a number')

interface Person {
  readonly name: string
  readonly age: number
}

(() => {
  const apS = A.apS(E.getApplicativeValidation(RR.getUnionSemigroup(pipe(string.Semigroup, S.intercalate(', ')))))

  const lift = <E, A, B, C extends string>(action: (a: B) => E.Either<E, A>, name: C): (a: B) => E.Either<RR.ReadonlyRecord<string, E>, A> => (a) => pipe(action(a), E.mapLeft((e) => ({ [name]: e })));

  const parsePerson = (input: Record<string, unknown>) =>
    pipe(
      E.Do,
      apS('name',lift(parseString, "name" as const)(input.name)),
      apS('age', lift(parseNumber, "age" as const)(input.age))
    )

  console.log(parsePerson({}))
})();

I need the return type of parsePerson(...), specifically it's Either.left to be structurally similar to it's Either.right


So,

the return type of parsePerson(...) is

const parsePerson: (input: Record<string, unknown>) => E.Either<Readonly<Record<string, string>>, {
    readonly name: string;
    readonly age: number;
}>

but I need it look like this

const parsePerson: (input: Record<string, unknown>) => E.Either<
    readonly name: string;
    readonly age: string;
>, {
    readonly name: string;
    readonly age: number;
}>
v0rs4
  • 106
  • 5

0 Answers0