1.2.1 • Published 7 months ago

prover-ts v1.2.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

Prover-ts

Prover-ts is a small lightweight package to parse through unknown shapes, providing strong typing.

Installation

npm install prover-ts

Usage

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.

Supported types

  • String

    • nonEmpty

      • expects a non-empty string.

        const result = prover.string().nonEmpty().parse("Test");
        
        // Throws
        prover.string().nonEmpty().parse("");
    • max

      • Parameters

        maxLength {number} expected max characters

        const result = prover.string().max(5).parse("Hello");
        
        // Throws
        prover.string().max(5).parse("Hello World");
    • min

      • Parameters

        minLength {number} expected min characters

        const result = prover.string().min(5).parse("Hello");
        
        // Throws
        prover.string().min(5).parse("Hi");
    • length

      • Parameters

        length {number} expected string length

        const result = prover.string().length(5).parse("Hello");
        
        // Throws
        prover.string().length(5).parse("Hello again");
    • includes

      • Parameters

        toInclude {string} expected string to be present

        const 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 string

        const 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 string

        const result = prover.endsWith("world!").parse("Hello, world!");
        
        // Throws
        prover.endsWith("world!").parse("Hello, universe!");
    • regex

      • Parameters

        pattern {string | RegExp} pattern to match

        const 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 string

        const isUpperCase = (arg: string) => arg === arg.toUpperCase();
        const result = prover.func(isUpperCase).parse("HELLO");
        
        // Throws
        prover.func(isUpperCase).parse("Hello");
  • Number

    • 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 than

        const result = prover.number().gt(42).parse(69);
        
        // Throws
        prover.number().gt(42).parse(22);
    • gte

      • Parameters

        comp {number} number to be greater or equal than

        const result = prover.number().gte(42).parse(42);
        
        // Throws
        prover.number().gte(42).parse(24);
    • lt

      • Parameters

        comp {number} number to be lesser than

        const result = prover.number().lt(42).parse(24);
        
        // Throws
        prover.number().lt(42).parse(69);
    • lte

      • Parameters

        comp {number} number to be lesser or equal to

        const result = prover.number().lte(42).parse(42);
        
        // Throws
        prover.number().lte(42).parse(69);
    • multiple

      • Parameters

        comp {number} number to be multiple of

        const 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 number

        const isEven = (arg) => arg % 2 === 0;
        
        const result = prover.number().func(isEven).parse(10);
        
        // Throws
        prover.number().func(isEven).parse(3);
  • Object

    • 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[] };
  • Record

    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 });
  • Array

    • max

      • Parameters {nElements} number of max elements that should be inside the array

        const 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 array

        const 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 array

        const 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)[];
  • Tuple

    • 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.

Contributing

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.

License

MIT

1.2.1

7 months ago

1.2.0

7 months ago

1.1.1

7 months ago

1.0.2

7 months ago

1.0.1

7 months ago

1.0.0

7 months ago

0.0.6

7 months ago