Prover-ts is a small lightweight package to parse through unknown shapes, providing strong typing.
npm install prover-ts
import { prover } from "prover-ts";
/*
* API returns an object. A familiar shape is known, but strong confirmation is needed.
* Prover-ts can help on that.
*/
try {
const unknownShape = await fetchingSomething(); // unknown
const parsedShape = prover
.object({ name: prover.string(), lastName: prover.string(), age: prover.number() })
.parse(unknownShape);
} catch (error) {
console.log(error);
}
parsedShape
would be typed like this:
const parsedShape: {
name: string;
lastName: string;
age: number;
};
prover-ts would return an error if the object did not match the expected shape. Future releases might change this.
-
-
nonEmpty
-
expects a non-empty string.
const result = prover.string().nonEmpty().parse("Test"); // Throws prover.string().nonEmpty().parse("");
-
-
max
-
Parameters
maxLength {number}
expected max charactersconst result = prover.string().max(5).parse("Hello"); // Throws prover.string().max(5).parse("Hello World");
-
-
min
-
Parameters
minLength {number}
expected min charactersconst result = prover.string().min(5).parse("Hello"); // Throws prover.string().min(5).parse("Hi");
-
-
length
-
Parameters
length {number}
expected string lengthconst result = prover.string().length(5).parse("Hello"); // Throws prover.string().length(5).parse("Hello again");
-
-
includes
-
Parameters
toInclude {string}
expected string to be presentconst result = prover.string().includes("Hello").parse("Hello World"); // Throws prover.string().includes("Hello").parse("Hi World");
-
-
startsWith
-
Parameters
toStartWith {string}
expected characters matching the beginning of the stringconst result = prover.startsWith("Hello").parse("Hello, world!"); // Throws prover.startsWith("Hello").parse("Hi, world!");
-
-
endsWith
-
Parameters
endsWith {string}
expected characters matching the end of the stringconst result = prover.endsWith("world!").parse("Hello, world!"); // Throws prover.endsWith("world!").parse("Hello, universe!");
-
-
regex
-
Parameters
pattern {string | RegExp}
pattern to matchconst result = prover.regex(/^\d{4}$/).parse("1234"); // Throws prover.regex(/^\d{4}$/).parse("12345");
-
-
email
-
expects an email
const result = prover.email().parse("test@gmail.com"); // Throws prover.email().parse("invalid-email");
-
-
date
-
expects a date formatted yyyy-mm-dd
const result = prover.date().parse("2023-05-30"); // Throws prover.date().parse("30/05/2023");
future implementation might support different formats
-
-
numeric
-
expects a numeric string
const result = prover.numeric().parse("12345"); // Throws prover.numeric().parse("abc12345");
-
-
alphanumeric
-
expects an alphanumeric string
const result = prover.alphanumeric().parse("abc123"); // Throws prover.alphanumeric().parse("abc@123");
-
-
ipv4
-
expects an ipv4 matching string
const result = prover.ipv4().parse("192.168.0.1"); // Throws prover.ipv4().parse("256.256.256.256");
-
-
func
-
Parameters
predicate {(arg: string) => boolean}
predicate function responsible to validate stringconst isUpperCase = (arg: string) => arg === arg.toUpperCase(); const result = prover.func(isUpperCase).parse("HELLO"); // Throws prover.func(isUpperCase).parse("Hello");
-
-
-
-
positive
-
expects a positive number.
const result = prover.number().positive().parse(1); // Throws prover.number().positive().parse(-1);
-
-
negative
-
expects a negative number.
const result = prover.number().negative().parse(-1); // Throws prover.number().negative().parse(1);
-
-
equal
-
toEqual {number}
expects an equal number.const result = prover.number().equal(42).parse(42); // Throws prover.number().equal(42).parse(-1);
-
-
gt
-
Parameters
comp {number}
number to be greater thanconst result = prover.number().gt(42).parse(69); // Throws prover.number().gt(42).parse(22);
-
-
gte
-
Parameters
comp {number}
number to be greater or equal thanconst result = prover.number().gte(42).parse(42); // Throws prover.number().gte(42).parse(24);
-
-
lt
-
Parameters
comp {number}
number to be lesser thanconst result = prover.number().lt(42).parse(24); // Throws prover.number().lt(42).parse(69);
-
-
lte
-
Parameters
comp {number}
number to be lesser or equal toconst result = prover.number().lte(42).parse(42); // Throws prover.number().lte(42).parse(69);
-
-
multiple
-
Parameters
comp {number}
number to be multiple ofconst result = prover.number().multiple(5).parse(10); // Throws prover.number().multiple(3).parse(10);
-
-
save
-
Requires number to be a safe integer, meaning, between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER
const result = prover.number().save().parse(10); // Throws prover.number().save().parse(Infinity);
-
-
finite
-
Requires number to be in between Infinity and -Infinity
const result = prover.number().finite().parse(69); // Throws prover.number().finite().parse(Infinity);
-
-
func
-
Parameters
func {(arg: number) => boolean}
predicate function responsible to validate numberconst isEven = (arg) => arg % 2 === 0; const result = prover.number().func(isEven).parse(10); // Throws prover.number().func(isEven).parse(3);
-
-
-
-
safe
-
filters out unexpected properties
const result = prover .object({ name: prover.string().nonEmpty(), age: prover.number().positive() }) .safe() .parse({ name: "John", age: 30, address: ["street 1", "street 2"] });
Without calling safe(), result object would have a
address
property, since prover's default behavior would NOT filter out a property that was not expected to exist.
-
-
Other examples
-
const result = prover .object({ name: prover.string().nonEmpty(), age: prover.number().positive() }) .parse({ name: "John", age: 30 });
-
const result = prover .object({ name: prover.string().nonEmpty(), idNumber: prover.number().positive(), married: prover.boolean(), address: prover.array(prover.string()), }) .parse({ name: "John", idNumber: 12131313, married: true, address: ["hollywood, beverly hills"] });
Inferred correctly
const result: { name: string; idNumber: number; married: boolean; address: string[] };
-
-
-
When you only care about the values and their types
-
Examples
-
const result = prover.record(prover.string()).parse({ name: "John", lastName: "Doe" }); // Throws prover.record(prover.string()).parse({ name: "John", age: 30 });
-
-
-
-
max
-
Parameters
{nElements}
number of max elements that should be inside the arrayconst result = prover.array([prover.number()]).max(10).parse([1, 2, 3, 4, 5, 6]); // Throws prover.array([prover.number()]).max(2).parse([1, 2, 3, 4, 5, 6]);
-
-
min
-
Parameters
{nElements}
number of min elements that should be inside the arrayconst result = prover.array([prover.number()]).min(2).parse([1, 2, 3, 4, 5, 6]); // Throws prover.array([prover.number()]).min(10).parse([1, 2, 3, 4, 5, 6]);
-
-
size
-
Parameters
{nElements}
number of exact elements that should be inside the arrayconst result = prover.array([prover.number()]).size(6).parse([1, 2, 3, 4, 5, 6]); // Throws prover.array([prover.number()]).size(10).parse([1, 2, 3, 4, 5, 6]);
-
-
nonEmpty
const result = prover.array([prover.number()]).nonEmpty().parse([1, 2, 3, 4, 5, 6]); // Throws prover.array([prover.number()]).nonEmpty().parse([]);
-
Other Examples
const result = prover.array([prover.number(), prover.string()]).parse([1, 2, "3", 4, "5", 6]); // Throws prover.array([prover.number(), prover.string()]).parse([1, 2, "3", 4, "5", 6, true]);
Inferred correctly
const result: (string | number)[];
-
-
-
Examples
-
prover.tuple([prover.number(), prover.number(), prover.boolean()]).parse([1, 2, true]); // Throws prover.tuple([prover.number(), prover.number(), prover.boolean()]).parse([1, "2", true]);
-
-
Record and Tuple are still experimental features.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
Make sure to include changeset.