Skip to content

Commit 9252b43

Browse files
authored
Add Schema.ArrayEnsure (#1782)
1 parent 764d150 commit 9252b43

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
Add `Schema.ArrayEnsure`.

packages/effect/src/Schema.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,6 +3262,36 @@ export const NonEmptyArray = Struct_.lambda<NonEmptyArrayLambda>((schema) =>
32623262
make(new AST.Arrays(false, [schema.ast], [schema.ast]), { schema })
32633263
)
32643264

3265+
/**
3266+
* @category Arrays
3267+
* @since 4.0.0
3268+
*/
3269+
export interface ArrayEnsure<S extends Top> extends decodeTo<$Array<toType<S>>, Union<readonly [S, $Array<S>]>> {}
3270+
3271+
/**
3272+
* Decodes a single value or an array of values into an array.
3273+
*
3274+
* Decoding:
3275+
* - a single value is decoded as a one-element array
3276+
* - an array is decoded as-is
3277+
*
3278+
* Encoding:
3279+
* - a one-element array is encoded as a single value
3280+
* - arrays with more than one element are encoded as arrays
3281+
*
3282+
* @category Arrays
3283+
* @since 4.0.0
3284+
*/
3285+
export function ArrayEnsure<S extends Top>(schema: S): ArrayEnsure<S> {
3286+
return Union([schema, Array(schema)]).pipe(decodeTo(
3287+
Array(toType(schema)),
3288+
Transformation.transform({
3289+
decode: Arr.ensure,
3290+
encode: (array) => array.length === 1 ? array[0] : array
3291+
})
3292+
))
3293+
}
3294+
32653295
/**
32663296
* Schema type for an array with unique elements. Produced by {@link UniqueArray}.
32673297
*

packages/effect/test/schema/Schema.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,28 @@ Unexpected key with value "c"
940940
})
941941
})
942942

943+
it("ArrayEnsure", async () => {
944+
const schema = Schema.ArrayEnsure(Schema.FiniteFromString)
945+
const asserts = new TestSchema.Asserts(schema)
946+
947+
const decoding = asserts.decoding()
948+
await decoding.succeed("1", [1])
949+
await decoding.succeed(["1", "2"], [1, 2])
950+
await decoding.succeed([], [])
951+
await decoding.fail(null, `Expected string | array, got null`)
952+
await decoding.fail("a", `Expected a finite number, got NaN`)
953+
await decoding.fail(
954+
["a"],
955+
`Expected a finite number, got NaN
956+
at [0]`
957+
)
958+
959+
const encoding = asserts.encoding()
960+
await encoding.succeed([], [])
961+
await encoding.succeed([1], "1")
962+
await encoding.succeed([1, 2], ["1", "2"])
963+
})
964+
943965
describe("NonEmptyArray", () => {
944966
it("should expose the item schema", () => {
945967
const schema = Schema.NonEmptyArray(Schema.String)

0 commit comments

Comments
 (0)