Skip to content

Instantly share code, notes, and snippets.

@reidev275
Last active September 11, 2019 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reidev275/9f88f627090d132d229b7f61a82ee721 to your computer and use it in GitHub Desktop.
Save reidev275/9f88f627090d132d229b7f61a82ee721 to your computer and use it in GitHub Desktop.
import * as V from "../src/validation";
import * as PV from "../src/predValidation";
// a custom error type
interface ErrorType {
path: string;
error: string;
}
// some validations
const notBlank = (property: string, s: string): V.Validation<ErrorType> =>
(s || "").length > 0
? V.success()
: V.failure([{ path: property, error: `${property} was blank` }]);
const positive = (property: string, n: number): V.Validation<ErrorType> =>
n > 0
? V.success()
: V.failure([{ path: property, error: `${property} was negative` }]);
// a non trivial model with child relationship
type Package = { label: string; qty: number };
type Item = { itemNumber: string; packages: Package[] };
// validate a single package
const packageValidation: PV.PredValidation<Package, ErrorType> = (p: Package) =>
V.combine(positive("qty", p.qty), notBlank("label", p.label));
// a helper that allows us to prepend error paths with index info
const prefixIndex = (property: string) => (
e: ErrorType,
i: number
): ErrorType => ({
...e,
path: `${property}[${i}].${e.path}`
});
// lift packageValidation to work on an array of Packages.
// if an item has an error prefix the path with packages[indexInArray]
const packagesValidation: PV.PredValidation<Package[], ErrorType> = PV.all(
packageValidation,
prefixIndex("packages")
);
// combine packagesValidation with a notBlank to validate an Item
const itemValidation: PV.PredValidation<Item, ErrorType> = PV.combine(
(i: Item) => notBlank("itemNumber", i.itemNumber),
(i: Item) => packagesValidation(i.packages)
);
// an invalid item
const invalidItem = {
itemNumber: "",
packages: [
{ label: "", qty: -2 },
{ label: "", qty: 2 },
{ label: "pack", qty: 10 }
]
};
console.log(itemValidation(invalidItem));
// { kind: 'Failure',
// errors:
// [ { path: 'itemNumber', error: 'itemNumber was blank' },
// { path: 'packages[0].qty', error: 'qty was negative' },
// { path: 'packages[0].label', error: 'label was blank' },
// { path: 'packages[1].label', error: 'label was blank' } ] }
// a valid item
const validItem = {
itemNumber: "123",
packages: [{ label: "each", qty: 1 }, { label: "pack", qty: 10 }]
};
console.log(itemValidation(validItem));
// { kind: 'Success' }
// lift itemValidation to work with an array of Items
const itemsValidation: PV.PredValidation<Item[], ErrorType> = PV.all(
itemValidation,
prefixIndex("")
);
const items = [validItem, invalidItem];
console.log(itemsValidation(items));
// { kind: 'Failure',
// errors:
// [ { path: '[1].itemNumber', error: 'itemNumber was blank' },
// { path: '[1].packages[0].qty', error: 'qty was negative' },
// { path: '[1].packages[0].label', error: 'label was blank' },
// { path: '[1].packages[1].label', error: 'label was blank' } ] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment