From 20f55ec3539a8e34fe5372c7ba20624fc6d1020e Mon Sep 17 00:00:00 2001 From: Titouan CREACH Date: Fri, 6 Dec 2024 12:49:14 +0100 Subject: [PATCH] add Schema.headNonEmpty on Schema.NonEmptyArray (#3983) Co-authored-by: Giulio Canti --- .changeset/violet-spoons-compare.md | 5 ++++ packages/effect/src/Schema.ts | 13 ++++++++++ .../Schema/Schema/Array/headNonEmpty.test.ts | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 .changeset/violet-spoons-compare.md create mode 100644 packages/effect/test/Schema/Schema/Array/headNonEmpty.test.ts diff --git a/.changeset/violet-spoons-compare.md b/.changeset/violet-spoons-compare.md new file mode 100644 index 00000000000..f5e26fb5a08 --- /dev/null +++ b/.changeset/violet-spoons-compare.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +Add Schema.headNonEmpty for Schema.NonEmptyArray diff --git a/packages/effect/src/Schema.ts b/packages/effect/src/Schema.ts index 88376f6afaa..0e4021023ba 100644 --- a/packages/effect/src/Schema.ts +++ b/packages/effect/src/Schema.ts @@ -6014,6 +6014,19 @@ export const head = (self: Schema, I, R>): SchemaClass { strict: true, decode: array_.head, encode: option_.match({ onNone: () => [], onSome: array_.of }) } ) +/** + * Get the first element of a `NonEmptyReadonlyArray`. + * + * @category NonEmptyReadonlyArray transformations + * @since 3.12.0 + */ +export const headNonEmpty = (self: Schema, I, R>): SchemaClass => + transform( + self, + getNumberIndexedAccess(typeSchema(self)), + { strict: true, decode: array_.headNonEmpty, encode: array_.of } + ) + /** * Retrieves the first element of a `ReadonlyArray`. * diff --git a/packages/effect/test/Schema/Schema/Array/headNonEmpty.test.ts b/packages/effect/test/Schema/Schema/Array/headNonEmpty.test.ts new file mode 100644 index 00000000000..51e113134de --- /dev/null +++ b/packages/effect/test/Schema/Schema/Array/headNonEmpty.test.ts @@ -0,0 +1,26 @@ +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" +import { describe, it } from "vitest" + +describe("headNonEmpty", () => { + it("decoding", async () => { + const schema = S.headNonEmpty(S.NonEmptyArray(S.NumberFromString)) + await Util.expectDecodeUnknownSuccess(schema, ["1"], 1) + await Util.expectDecodeUnknownFailure( + schema, + ["a"], + `(readonly [NumberFromString, ...NumberFromString[]] <-> number | number) +└─ Encoded side transformation failure + └─ readonly [NumberFromString, ...NumberFromString[]] + └─ [0] + └─ NumberFromString + └─ Transformation process failure + └─ Expected NumberFromString, actual "a"` + ) + }) + + it("encoding", async () => { + const schema = S.headNonEmpty(S.NonEmptyArray(S.NumberFromString)) + await Util.expectEncodeSuccess(schema, 1, ["1"]) + }) +})