diff --git a/CHANGELOG.md b/CHANGELOG.md
index 640853e..1d59668 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
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 21.0.0 (unreleased)
+
+This release renames `nullable` to `nullOr` to be consistent with `undefinedOr`.
+
### Version 20.1.0 (2023-10-30)
This release adds a `JSON` object with `parse` and `stringify` methods, similar to the standard global `JSON` object. The difference is that tiny-decoder’s versions also take a `Codec`, which makes them safer. Read more about it in the documentation.
diff --git a/README.md b/README.md
index 53e6b7a..c6ebb1e 100644
--- a/README.md
+++ b/README.md
@@ -121,7 +121,7 @@ Here’s a summary of all codecs (with slightly simplified type annotations) and
- Of different types: [multi](#multi)
- Of tagged objects: [fieldsUnion](#fieldsunion) with [tag](#tag)
- With undefined: [undefinedOr](#undefinedor)
- - With null: [nullable](#nullable)
+ - With null: [nullOr](#nullOr)
- Other unions: [untagged union example](examples/untagged-union.test.ts)
- Intersections: [intersection example](examples/fieldsUnion-with-common-fields.test.ts)
- Transformation: [map](#map), [flatMap](#flatmap)
@@ -320,7 +320,7 @@ Here’s a summary of all codecs (with slightly simplified type annotations) and
T | undefined |
-nullable |
+nullOr |
(codec: Codec<T>) =>
Codec<T | null> |
null or … |
@@ -842,7 +842,7 @@ Notes:
- Using `undefinedOr` does _not_ make a field in an object optional. It only allows the field to be `undefined`. Similarly, using the [field](#field) function to mark a field as optional does not allow setting the field to `undefined`, only omitting it.
- JSON does not have `undefined` (only `null`). So `undefinedOr` is more useful when you are decoding something that does not come from JSON. However, even when working with JSON `undefinedOr` still has a use: If you infer types from codecs, using `undefinedOr` on object fields results in `| undefined` for the type of the field, which allows you to assign `undefined` to it which is occasionally useful.
-### nullable
+### nullOr
```ts
function nullOr(
@@ -1011,7 +1011,7 @@ const myError: DecoderError = {
};
```
-`orExpected` exists so that `undefinedOr` and `nullable` can say that `undefined` and/or `null` also are expected values.
+`orExpected` exists so that `undefinedOr` and `nullOr` can say that `undefined` and/or `null` also are expected values.
## format
diff --git a/index.ts b/index.ts
index f1a2280..6f86ce5 100644
--- a/index.ts
+++ b/index.ts
@@ -859,7 +859,7 @@ export function undefinedOr(
};
}
-export function nullable(
+export function nullOr(
codec: Codec,
): Codec {
return {
diff --git a/tests/codecs.test.ts b/tests/codecs.test.ts
index 5281599..b0b7e37 100644
--- a/tests/codecs.test.ts
+++ b/tests/codecs.test.ts
@@ -15,7 +15,7 @@ import {
InferEncoded,
map,
multi,
- nullable,
+ nullOr,
number,
primitiveUnion,
record,
@@ -2432,9 +2432,9 @@ describe("undefinedOr", () => {
});
});
-describe("nullable", () => {
- test("nullable string", () => {
- const codec = nullable(string);
+describe("nullOr", () => {
+ test("nullOr string", () => {
+ const codec = nullOr(string);
expectType, string | null>>(true);
expectType, string | null>>(true);
@@ -2457,7 +2457,7 @@ describe("nullable", () => {
});
test("with default", () => {
- const codec = map(nullable(string), {
+ const codec = map(nullOr(string), {
decoder: (value) => value ?? "def",
encoder: (value) => value,
});
@@ -2475,7 +2475,7 @@ describe("nullable", () => {
});
test("with undefined instead of null", () => {
- const codec = map(nullable(string), {
+ const codec = map(nullOr(string), {
decoder: (value) => value ?? undefined,
encoder: (value) => value ?? null,
});
@@ -2493,11 +2493,11 @@ describe("nullable", () => {
expect(codec.encoder("a")).toBe("a");
});
- test("nullable field", () => {
+ test("nullOr field", () => {
type Person = Infer;
const Person = fieldsAuto({
name: string,
- age: nullable(number),
+ age: nullOr(number),
});
expectType>(true);
@@ -2551,7 +2551,7 @@ describe("nullable", () => {
void person;
});
- test("nullable custom codec", () => {
+ test("nullOr custom codec", () => {
const codec: Codec = {
decoder: (value) => ({
tag: "DecoderError",
@@ -2567,7 +2567,7 @@ describe("nullable", () => {
},
};
- expect(run(nullable(codec), 1)).toMatchInlineSnapshot(`
+ expect(run(nullOr(codec), 1)).toMatchInlineSnapshot(`
At root:
fail
Got: 1
@@ -2580,9 +2580,9 @@ describe("nullable", () => {
);
});
- test("nullable higher up the chain makes no difference", () => {
+ test("nullOr higher up the chain makes no difference", () => {
const codec = fieldsAuto({
- test: nullable(fieldsAuto({ inner: string })),
+ test: nullOr(fieldsAuto({ inner: string })),
});
expect(run(codec, { test: 1 })).toMatchInlineSnapshot(`
@@ -2600,8 +2600,8 @@ describe("nullable", () => {
`);
});
- test("undefinedOr and nullable", () => {
- const codec = undefinedOr(nullable(nullable(undefinedOr(string))));
+ test("undefinedOr and nullOr", () => {
+ const codec = undefinedOr(nullOr(nullOr(undefinedOr(string))));
expectType, string | null | undefined>>(true);
expectType<