effect icon indicating copy to clipboard operation
effect copied to clipboard

S.firstOfArray to extract the first element of an array to match a given schema

Open jessekelly881 opened this issue 2 years ago • 0 comments

I found myself needing to extract the first element of an array from api request that matched a given schema and I suspect that something similar might be useful as part of the core lib. Actually, similar utility fns might be useful in general.

import * as S from "@effect/schema/Schema";
import * as PR from "@effect/schema/ParseResult";
import * as RA from "@effect/data/ReadonlyArray";

/**
 * Finds the first el in an array that matches the schema.
 */
const firstOfArray = <I, A>(schema: S.Schema<I, A>) => {
  const is = S.is(schema);
  const encodeSync = S.encodeSync(schema);
  const decodeSync = S.decodeSync(schema);

  return S.transformResult(
    S.array(S.unknown),
    schema,
    (s) => {
      const res = RA.findFirst(s, is);
      if (res._tag === "Some") {
        return PR.success(encodeSync(res.value));
      } else return PR.failure(PR.type(schema.ast, s));
    },
    (s) => PR.success([decodeSync(s)])
  );
};

// example use

const s = S.struct({
  descriptions: firstOfArray(
    S.struct({
      lang: S.literal("en"),
      description: S.string,
    })
  ),
});

const res = S.parseSync(s)({
  descriptions: [
      { lang: "fr", description: "des" },
      { lang: "en", description: "des" }
  ],
});

console.log(res); // { descriptions: { lang: 'en', description: 'des' } }

jessekelly881 avatar Aug 05 '23 23:08 jessekelly881