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

typify

v0.2.10

Published

Runtime type-checking for JavaScript.

Downloads

3,315

Readme

typify

Runtime type-checking.

Build Status NPM version Dependency Status Code Climate

Getting Started

Install the module with: npm install typify

Synopsis

// Browser
// <script src="dist/typify.standalone.js" type="text/javascript"></script>

// Node
var typify = require("typify");

/*
 * `sum` function takes either two numbers or two strings as a parameter,
 * and returns a number or a string respectively.
 */
var sum = typify("sum :: a : number|string => a -> a -> a", function (a, b) {
    return a + b;
});

/*
 * `toArray` function takes either an array of numbers or a single number,
 * and returns an array of numbers.
 *
 * We could write a more general, polymorphic function with type signature
 * `toArray :: a : *, (array a)|a -> array a`, where `*` means _any type_.
 *
 * Unfortunately any type `*` is seriously any.
 * Types as *typify* understands them, are more like Java's interfaces or Haskell's typeclasses.
 * Of course, we can iterate through them all, but we cannot deduce the most principal type (because it doesn't exist).
 * So eg. function signature `id :: a : *, a -> a` behaves similarly to `id :: * -> *`, which isn't strict enough.
 */
var toNumberArray = typify("toNumberArray :: (array number)|number -> array number", function (a) {
    return Array.isArray(a) ? a : [a];
});

/*
 * `myParseInt` takes a string and an optional number (radix) and returns a number.
 */
var myParseInt = typify("myParseInt :: string -> number? -> number", function (n, radix) {
    return parseInt(n, radix || 10)
});

/*
 * `foo` takes at least one number parameter and returns a number.
 */
var foo = typify("foo :: number -> number.. -> number", function (a) {
    return a + arguments.length;
});

Documentation

API

  • typify(functionSpec, fun) - decorate function with run-time type check
  • typify.create() - create new typify environment
  • typify.type(typename, checkFun) - add new type with user-supplied existence check
  • typify.record(typename, recordspec) - add new record type
  • typify.alias(typename, typespec) - give name to the compound type
  • typify.mutual(typespecs) - define multiple (possibly mutually recursive) types at once
  • typify.instance(name, cls) - add new instance type
  • typify.check(typename, value) -> bool - check membership of value in the type. check is autoCurried

Checkable type

Checkable means, that given an object you can check whether an object is or isn't of the particular type. For example number is checkable type, given any object you can tell if it's a number.

typify.check('number', 1); // => true
typify.check('number', 'foobar'); // => false

You could use typify.assert for type assertions:

typify.check('number', 'foo'); // will throw `TypeError` exception

There are few predefined checkable types:

  • number
  • integer
  • nat: non-negative integer
  • positive x
  • nonnegative x
  • finite x
  • string
  • boolean
  • date
  • regexp
  • function, fn
  • array a
  • map a
  • tuple a b...
  • null, undefined, infinity, ninfinity, nan, true and false

Formal syntax of checkable type declaration:

  • checkable type σ ::= σ_or
    • σ_or ::= σ_and (| σ_and)*
    • σ_and ::= σ_poly (& σ_poly)*
    • σ_poly ::= typename σ_opt+ | σ_opt
    • σ_opt = σ_term | σ_term ?
    • σ_record ::= { } | { σ_pair (, σ_pair)* }
    • σ_pair ::= identifier : σ_term
    • σ_term ::= * | α | literal | typename | ( σ_alt )
  • type variable α ::= identifier
  • literal ::= /\d+/ | /"[^"]"/ | /'[^']'/ | true | false | null | undefined | nan | infinity | ninfinity
  • identifier, typename ::= /[a-zA-Z_][a-zA-Z0-9_]*/

Function type

Function types are difficult to check. Given a function object, only you can tell, it's a function object. To be more precise, you can decorate your function with function type signature to verify parameters' and result's types, but the check will occur only when function is executed ie. run-time.

var add = typify("add :: number -> number -> number", function (a, b) {
    return a + b;
});

console.log(add(1, 2)); // ok
console.log(add("foo", "bar")); // throws TypeError

Formal syntax of function type declaration:

  • function type λ ::= ν μ | ν Γ (σ ->)* ρ σ
  • action μ ::= -> τ
  • context Γ ::= α : Σ (, α : Σ)* => | ε
  • typeset Σ ::= σ_poly (| σ_poly)*
  • rest parameters ρ ::= σ ... -> | ... -> | ε
  • function name ν ::= identifier :: | ε

New types

New types can be added with typify.type method:

typify.type("char", function(n) {
    return typeof n === "string" && n.length === 1;
});

Note: opaque type checks should return true, other truthy values will be considered errorneous in later versions.

You can give names to (recursive) compound types with typify.alias:

typify.alias("numstr", "number|string"); // numbers or strings
typify.alias("rarray", "array rarray"); // arrays of itself, eg [[[[[[]]]]]

For mutually recursive types use typify.mutual:

typify.mutual({
    "foo": "list bar",
    "bar": "list foo",
});

Also you can define record types with typify.record:

typify.record("person", {
    name: "string",
    age: "number",
});

Record types may be recursive:

typ.record("bst", {
    left: "bst?",
    right: "bst?",
});

If you prefer instanceof, there is typify.instance helper in place:

function Foo() {}
typ.instance("Foo", Foo);
typ.check("Foo", new Foo());

Hygiene usage

If you don't want to use global type database, you can create your own instance of typify:

// In browser
var myTypify = typify.create();

// or alternatively, using "let-binding":
(function (typify) {
    // use typify as it would be global
}(typify.create()));

// In node
var typify = require("typify").create();

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using npm test command.

Release History

  • 0.2.9 Closed records

    • typify.record(name, def, closed)
  • 0.2.8

    • Change date and regexp checks to work in multiframe environments #34
    • Fix typo in README.md #35
    • Update dependencies
  • 0.2.7

    • Use make
  • 0.2.6

    • Updated dependencies
  • 0.2.5

    • typify.assert
    • Added note about opaque type checks (typify.type)
  • 0.2.4

    • arguments built-in type
    • any built-in type. Like * but not optional
    • typified most of functions
  • 0.2.3

    • fn shorthand for the function type
    • typify.wrap to typify modules
    • istanbul code covarage as part of the test suite
    • typify.adt helper for specifying abstract data types -like structures
    • infinity, ninfinity and nan literals
    • unified implementation of typify.type, typify.alias and typify.record.
      • The latter two will be deprecated in 0.3.0 and removed in 0.4.0
  • 0.2.2

    • mutually recursive types
    • instanceof types
  • 0.2.1

    • anonymous record types
    • tuple, numeric types
    • mocha test-suite
    • major code refactor
  • 0.2.0

    • Recursive record types
    • Recursive aliases
    • Intersection types
    • Hygiene type environments
  • 0.1.1

    • Record type
    • Fixed typos in README.md
  • 0.1.0 Initial release

License

Copyright (c) 2013 Oleg Grenrus. Licensed under the BSD3 license.

Related work

Javascript

Others

Gradual typing (of existing languages)