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

type-definitions

v0.2.0

Published

Define and validate types in js

Downloads

24

Readme

type-definitions

The purpose of this package is to allow for defining type/object structure in an easily recognizable JSON format. An example definition might look something like:

import { defineType } from 'type-definitions';

const myTypeDefinition = defineType({
  foo: String,
  bar: Number,
  baz: {
    test: Boolean,
    something: [String]
  }
})

It also offers validation of values based on those definitions:

import { defineType } from 'type-definitions';

const aNumber = defineType(Number);

aNumber.isOfType(2); // true
aNumber.isOfType("test"); // false


const arrayOfStringsOrNumbers = defineType([String, Number]);
arrayOfStringsOrNumbers.isOfType([1, "test"]); // true
arrayOfStringsOrNumbers.isOfType([1, "test", true]); // false

const complexObject = defineType({
  a: Number,
  b: String,
  c: {
    d: [String],
    e: Boolean
  }
});

complex.isOfType({
  a: 2,
  b: "test",
  c: {
    d: ["some", "value"],
    e: true
  }
}); // true

complex.isOfType({
  a: 2,
  b: "test",
  c: {
    d: ["some", "value"],
    e: "true"
  }
}); // false (a.e !== Boolean)

Finally, it offers a way to construct objects of a given type and set defaults for that construction:

import { defineType, defaultValue, types } from 'type-definition';

const defaultString = defineType(String);
const fooString = defineType(defaultValue(String, "foo"));
const barString = types.String.withDefault("bar");

defaultString.create(); // ''
fooString.create() // 'foo'
barString.create() // 'bar'
barString.create("some other string") // 'some other string'
barString.create(2) // throws error, invalid type


const customObject = types.Object.withDefinition({
  a: String,
  b: types.Number.withDefault(5),
  c: {
    d: Boolean,
    e: defaultValue(Boolean, true)
  }
})

customObject.create() // { a: '', b: 5, c: { d: false, e: true } }
customObject.create({ a: 'test', c: { d: true }}); // { a: 'test', b: 5, c: { d: true, e: true } }

defineType

This function will process the input and return the representation as a class with an isOfType static function. It is primarily for coercing native representations, and will pass through the package-defined types. Therefore it's always good to wrap your definitions in this so that they will support as much definition styles as possible.

Types

String

Validates true for string values (ie "test").

Default value: ""

Using package type:

import { types, defineType } from 'type-definitions';

const aString = defineType(types.String);

This also supports coercion from native String:

const aString = defineType(String);

Number

Validates true for number values (ie 1, 1.23, Infinity, NaN, 1.0003e+23).

Default value: 0

Using package type:

import { types, defineType } from 'type-definitions';

const aNumber = defineType(types.Number);

This also supports coercion from native Number:

const aNumber = defineType(Number);

Boolean

Validates true for boolean values (ie true, false)

Default value: false

Using package type:

import { types, defineType } from 'type-definitions';

const aBool = defineType(types.Boolean);

This also supports coercion from native Boolean:

const aBool = defineType(Boolean);

Array

Validates true for any array (ie [], ["test"], ["test", 2, true])

Default value: []

Using package type:

import { types, defineType } from 'type-definitions';

const anArray = defineType(types.Array);

This also supports coercion from native Array or empty Array literal ([]):

const anArray = defineType(Array);
const anotherArray = defineType([]);

Array.ofType(type)

Validates true for any array that matches type, including empty arrays (ie for types.Array.ofType(type.String), [] or ["test"])

You can also make an of Array of multiple types which will set the type to a Union of the types supplied

Default value: []

Using package type:

import { types, defineType } from 'type-definitions';

const anArrayOfStrings = defineType(types.Array.ofType(types.String));

This also supports coercion from an Array literal with types as members ([String], [String, Number]):

const anArrayOfStrings = defineType([String]);
const anArrayOfStringsOrNumbers = defineType([String, Number]);

Object

Validates true for an object ({}, new class Test {}). Does not match null or arrays.

Default value: {}

Using package type:

import { types, defineType } from 'type-definitions';

const anObject = defineType(types.Object);

This also supports coercion from native Object and an empty object literal ({})""

const anObject = defineType(Object);
const anotherObject = defineType({});

Object.withDefinition(objectDefinition)

Validates true for objects that match the defined structure. Note: it will match objects with additional properties not included in the definition by default. You can include the strict

Default value: default values of individual props

Using package type:

import { types, defineType } from 'type-definitions';

const anObject = defineType(types.Object.withDefinition({
  foo: String,
  bar: Number
}));

This also supports coercion from an Object literal with members ({foo: String, bar: Number }):

const anObject = defineType({
  foo: String,
  bar: Number
});

Object.withDefinition(objectDefinition).strict

Same as Object.withDefinition(objectDefinition) except it also validates that value does not have any additional keys

Default value: default values of individual props

Using package type:

import { types, defineType } from 'type-definitions';

const anObject = defineType(types.Object.withDefinition({
  foo: String,
  bar: Number
}).strict);

There is no native representation of this, however you can import the strict function and use that to wrap native types:

import { defineType, strict } from 'type-definitions';

const aStringOrNull = defineType(strict({
  foo: String,
  bar: Number
}));

Object.keyValuePair(valueType)

Validates true for an object where all values match the supplied value type.

Default value: {}

Using package type:

import { types, defineType } from 'type-definitions';

const aHashOfStrings = defineType(types.Object.keyValuePair(String));

There is no native representation for this

Any

Validates true for any value (allows null but excludes undefined).

Default value: null

Using package type:

import { types, defineType } from 'type-definitions';

const anyType = defineType(types.Any);

There is no native representation for this

Union.ofType(...types)

Validates true for any value matches any of the union types.

Default value: default value of first type

Using package type:

import { types, defineType } from 'type-definitions';

const unionOfStringAndNumber = defineType(types.Union.ofType(String, Number));

There is no native representation of this, however you can import the unionOf function and use that to wrap native types:

import { defineType, unionOf } from 'type-definitions';

const unionOfStringAndNumber = unionOf(String, Number)

Optional

All built in types include can be modified to validate for null/undefined by appending the .optional modifier

Default value: null unless user specified

Using package type:

import { types, defineType } from 'type-definitions';

const aStringOrNull = defineType(types.String.optional);

There is no native representation of this, however you can import the optional function and use that to wrap native types:

import { defineType, unionOf } from 'type-definitions';

const aStringOrNull = optional(String)

Custom Classes

Custom classes can be supported by providing a static isOfType(val) method on your class. It will leverage whatever logic you put in this method for validation

Default value: Object.create(CustomClass)

class MyClass {
  static isOfType(val) {
    return val.__type === "myType"
  }
  get __type() { return "myType"; }
}

class SomeOtherClass {
  get __type() { return "!!!"; }
}

defineType(MyType).isOfType(new SomeOtherClass()); // false

If you use a class that does not define state isOfType(val) then isOfType will fall back to using instanceof for validation

Type.withDefault() / Type.create()

Taking an exisitng type and calling .create(val) on it will construct an instance of of that type with the given value (assuming the provided value validates).

If no value is provided it will construct an object with the default value of an object (see defaults above)

If you would like to change the default value of an object there is a withDefault() static on all type extending from BaseType (or coerced via defineType) which takes a default value, validates it against the type and if it's value uses that as the default construction value. Additionally there is a defaultValue(type, val) method exported for use in wrapping native types

For objects, you can provide a partial value to .create() and it will use defaults to fill in other properties as it is able to.