Skip to content

Commit

Permalink
Rename the options for fieldsAuto and fieldsUnion
Browse files Browse the repository at this point in the history
  • Loading branch information
lydell committed Oct 22, 2023
1 parent ac0a10b commit 64b077d
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 27 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
Note: I’m currently working on several breaking changes to tiny-decoders, but I’m trying out releasing them piece by piece. The idea is that you can either upgrade version by version only having to deal with one or a few breaking changes at a time, or wait and do a bunch of them at the same time.

### Version 15.0.0 (unreleased)

This release changes the options parameter of `fieldsAuto` and `fieldsUnion` from:

```ts
{ exact = "allow extra" }: { exact?: "allow extra" | "throw" } = {}
```

To:

```ts
{ allowExtraFields = true }: { allowExtraFields?: boolean } = {}
```

This is because:

- A future tiny-decoders version will be return value based instead of throwing errors, so `"throw"` will not make sense anymore.
- tiny-decoders used to have a third alternative for that option – that’s why it’s currently a string union rather than a boolean. While at it, we could just as well simplify into a boolean.

### Version 14.0.0 (2023-10-22)

This release removes the `fields` function, which was deprecated in version 11.0.0. See the release notes for version 11.0.0 for how to replace `fields` with `fieldsAuto`, `chain` and custom decoders.
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ For example, `record(number)` decodes an object where the keys can be anything a
```ts
function fieldsAuto<Mapping extends FieldsMapping>(
mapping: Mapping,
{ exact = "allow extra" }: { exact?: "allow extra" | "throw" } = {},
{ allowExtraFields = true }: { allowExtraFields?: boolean } = {},
): Decoder<InferFields<Mapping>>;

type FieldsMapping = Record<string, Decoder<any> | Field<any, FieldMeta>>;
Expand Down Expand Up @@ -412,10 +412,10 @@ const userDecoder: Decoder<User> = fieldsAuto({
});
```

The `exact` option let’s you choose between ignoring extraneous data and making it a hard error.
The `allowExtraFields` option lets you choose between ignoring extraneous fields and making it an error.

- `"allow extra"` (default) allows extra properties on the object.
- `"throw"` throws a `DecoderError` for extra properties.
- `true` (default) allows extra fields on the object.
- `false` throws a `DecoderError` for extra fields.

See also the [Extra fields](examples/extra-fields.test.ts) example.

Expand Down Expand Up @@ -526,7 +526,7 @@ function fieldsUnion<
>(
decodedCommonField: DecodedCommonField,
variants: Variants,
{ exact = "allow extra" }: { exact?: "allow extra" | "throw" } = {},
{ allowExtraFields = true }: { allowExtraFields?: boolean } = {},
): Decoder<InferFieldsUnion<Variants[number]>>;
type Variant<DecodedCommonField extends string> = Record<
Expand Down
8 changes: 4 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ type InferFields<Mapping extends FieldsMapping> = Expand<

export function fieldsAuto<Mapping extends FieldsMapping>(
mapping: Mapping,
{ exact = "allow extra" }: { exact?: "allow extra" | "throw" } = {},
{ allowExtraFields = true }: { allowExtraFields?: boolean } = {},
): Decoder<InferFields<Mapping>> {
return function fieldsAutoDecoder(value): InferFields<Mapping> {
const object = unknownRecord(value);
Expand Down Expand Up @@ -172,7 +172,7 @@ export function fieldsAuto<Mapping extends FieldsMapping>(
}
}

if (exact !== "allow extra") {
if (!allowExtraFields) {
const unknownFields = Object.keys(object).filter(
(key) => !knownFields.has(key),
);
Expand Down Expand Up @@ -217,7 +217,7 @@ export function fieldsUnion<
>(
decodedCommonField: DecodedCommonField,
variants: Variants,
{ exact = "allow extra" }: { exact?: "allow extra" | "throw" } = {},
{ allowExtraFields = true }: { allowExtraFields?: boolean } = {},
): Decoder<InferFieldsUnion<Variants[number]>> {
if (decodedCommonField === "__proto__") {
throw new Error("fieldsUnion: commonField cannot be __proto__");
Expand All @@ -244,7 +244,7 @@ export function fieldsUnion<
)}) than before (${JSON.stringify(maybeEncodedCommonField)}).`,
);
}
const fullDecoder = fieldsAuto(variant, { exact });
const fullDecoder = fieldsAuto(variant, { allowExtraFields });
decoderMap.set(field_.tag.encoded, fullDecoder);
}

Expand Down
43 changes: 25 additions & 18 deletions tests/decoders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ describe("fieldsAuto", () => {
`);
});

describe("exact", () => {
describe("allowExtraFields", () => {
test("allows excess properties by default", () => {
expect(
run(fieldsAuto({ one: string, two: boolean }), {
Expand All @@ -474,20 +474,26 @@ describe("fieldsAuto", () => {
).toStrictEqual({ one: "a", two: true });
expect(
run(
fieldsAuto({ one: string, two: boolean }, { exact: "allow extra" }),
fieldsAuto({ one: string, two: boolean }, { allowExtraFields: true }),
{ one: "a", two: true, three: 3, four: {} },
),
).toStrictEqual({ one: "a", two: true });
});

test("throw on excess properties", () => {
test("fail on excess properties", () => {
expect(
run(fieldsAuto({ one: string, two: boolean }, { exact: "throw" }), {
one: "a",
two: true,
three: 3,
four: {},
}),
run(
fieldsAuto(
{ one: string, two: boolean },
{ allowExtraFields: false },
),
{
one: "a",
two: true,
three: 3,
four: {},
},
),
).toMatchInlineSnapshot(`
At root:
Expected only these fields:
Expand All @@ -502,7 +508,10 @@ describe("fieldsAuto", () => {
test("large number of excess properties", () => {
expect(
run(
fieldsAuto({ "1": boolean, "2": boolean }, { exact: "throw" }),
fieldsAuto(
{ "1": boolean, "2": boolean },
{ allowExtraFields: false },
),
Object.fromEntries(Array.from({ length: 100 }, (_, i) => [i, false])),
),
).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -549,7 +558,7 @@ describe("fieldsAuto", () => {
});

test("empty object", () => {
const decoder = fieldsAuto({}, { exact: "throw" });
const decoder = fieldsAuto({}, { allowExtraFields: false });
expect(decoder({})).toStrictEqual({});
expect(run(decoder, { a: 1 })).toMatchInlineSnapshot(`
At root:
Expand Down Expand Up @@ -681,7 +690,7 @@ describe("fieldsUnion", () => {
expect(decoder({ type: "B" })).toStrictEqual({ tag: "B" });
});

describe("exact", () => {
describe("allowExtraFields", () => {
test("allows excess properties by default", () => {
expect(
run(
Expand All @@ -700,7 +709,7 @@ describe("fieldsUnion", () => {
fieldsUnion(
"tag",
[{ tag: tag("Test"), one: string, two: boolean }],
{ exact: "allow extra" },
{ allowExtraFields: true },
),
{
tag: "Test",
Expand All @@ -713,15 +722,13 @@ describe("fieldsUnion", () => {
).toStrictEqual({ tag: "Test", one: "a", two: true });
});

test("throw on excess properties", () => {
test("fail on excess properties", () => {
expect(
run(
fieldsUnion(
"tag",
[{ tag: tag("Test"), one: string, two: boolean }],
{
exact: "throw",
},
{ allowExtraFields: false },
),
{
tag: "Test",
Expand Down Expand Up @@ -749,7 +756,7 @@ describe("fieldsUnion", () => {
fieldsUnion(
"tag",
[{ tag: tag("Test"), "1": boolean, "2": boolean }],
{ exact: "throw" },
{ allowExtraFields: false },
),
{
tag: "Test",
Expand Down

0 comments on commit 64b077d

Please sign in to comment.