npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

drytypes

v0.6.0

Published

A runtime type-validator with TypeScript in mind

Downloads

14

Readme

drytype

DryType is a runtime type-validation library with TypeScript in mind.

Runtime type validations are performed with a runtime type -- a DryType as I've called it throughout this library (beats me why).

A DryType is an object of the type:

export type DryType<T> = {
  validate(param: unknown): ValidationResult;
  // will throw if check fails
  strictValidate(
    param: unknown,
  ): ValidationResult;
  guard(param: unknown): param is T;
  // will throw if check fails
  strictGuard(param: unknown): param is T;
  toString(): string;

  intersect<S>(dt: DryType<S>): DryType<T & S>;
  /*
    errorFrom refers to whether the error from the
    first type, second type, or the default one is
    to be thrown.

    when this is 0 or undefined, the default error is used
    when this is 1, the 'left' error is used
    when this is 2 (or any other value), the 'right' error is used
  */
  union<S>(dt: DryType<S>, errorFrom?: number): DryType<T | S>;

  tag: string;
};

type ValidationResult = {
  success: boolean;
  message?: string;
  in?: string;
};

Might look fancy, but it's actually pretty simple.

validate(param: unknown) is used to check if a value param confirms to the type specification of that DryType, for example

import { String } from "drytype";

String.validate("hello"); // { success: true }
String.validate(20); // { success: false, message: "expected: string, got: number" }

strictValidate is the same as validate, with one big difference: when the validation fails, instead of returning a ValidationResult object, it throws a ValidationError(message)`.

guard and strictGuard are the same as validate and strictValidate, with the difference being that they are TypeScript guards instead of regular boolean returning functions.

union is the same as TypeScript |. A.union(B) returns a new DryType, which now checks if either A or B succeed. For example,

import { Number, String } from "drytype";

String.union(Number).validate(10); // { success: true }

union also takes a second parameter called fromError, which is used when both checks fail. If this is set to 0 or undefined, the default error will be used. If this is set to 1, the custom error from the DryType on the left will be used, if any. Any other value will make it use the custom error from the DryType on the right, if any.

intersect is the same as TypeScript &. A.intersect(B) returns a new DryType, which now checks if both A and B succeed. For example,

import { NumberGreaterThan, NumberLessThan } from "drytype";

// a number between between 5 and 10
NumberGreaterThan(5).intersect(NumberLessThan(10)).validate(7); // { success: true }

That covers what a DryType is composed of. A set of useful DryTypes have been provided by default in the modules directory for convenience. However, creating a new DryType is also very easy.

To create a new DryType, you can use makeDryType, which has the type:

const makeDryType = <T>(
  validator: (x: unknown) => ValidationResult,
  tag = "unknown",
): DryType<T>

Here's an example:

export const Function = makeDryType<Function>(
  (x) => typeof x == "function" ? { success: true } : { success: false },
  "function",
);

The generic type parameter is the type that the validated value should be of. This is used for TypeScript guards. The first parameter is a function that takes x: unknown and validates it. This function has to return a ValidationResult object, where success: boolean is a compulsory field. The message field will never be used if success is true, so you can skip it if success is true. However, if success is false, and you still skip the message field, a default message will be used, which is:

`expected: ${drytypeInQuestion.tag}, got: ${typeof (unknownParam)}${
  result.in == undefined ? "" : `, in: ${result.in}`
}`;

The only use of the in parameter in ValidationResult is to be inserted this way into the default error message. This can be useful for, say, Records where you need to give out additional information about where the validation failed.

NOTE: Also have a look at the tests for an example usage. Every provided DryType has at least one test present.

That's all you need to know to use this library. Happy validatin'!