arify

JavaScript function overloading. Let your function focus on its function.

Usage no npm install needed!

<script type="module">
  import arify from 'https://cdn.skypack.dev/arify';
</script>

README

arify

Let your function focus on its function

arify brings function overloading to JavaScript and allows for complex configurations of function arguments with an easy to use, self-documenting syntax. Eliminate those twenty lines of argument validation where you're checking types, lengths, and properties. Just arify them and let them do their thing.

Installation

npm i arify

Usage

View from the top:

import arify from 'arify'

const arified = arify(v => {
  v.string('one').number('two', 2)
  v.form('one', '?two')
}, args => {
  console.log(args.one, args.two)
})

arified('hello')
// -> 'hello', 2

Now let's break it down:

arify's default export is a function that you use to wrap your own functions.

import arify from 'arify'

The arify function takes a function as its first argument. This function should accept a single argument - typically called v - which is an instance of the arify configuration class.

const arified = arify(v => {})

You add parameters to your function by calling methods on this instance. In the example below, v.string is used to add a parameter named one. When calling the arified function, one would be required to be a string.

const arified = arify(v => {
  v.string('one')
})

But arify isn't quite ready - first we need to specify what forms our function can take. You do this using v.form:

const arified = arify(v => {
  v.string('one')
  v.form('one')
})

Now, we only have one argument in the examples above. But if we had more, we could call v.form multiple times:

const arified = arify(v => {
  v.string('one')
  v.number('two')
  v.boolean('isEven')

  v.form('one')
  v.form('one', 'two')
  v.form('one', 'isEven')
  v.form('one', 'two', 'isEven')
})

But this is getting a little verbose, isn't it? Let's shorten that by using the ? (optional) modifier. While we're at it, let's also add default values to v.number and v.boolean. We can also chain our type calls since they return the v instance.

const arified = arify(v => {
  v.string('one')
   .number('two', 2)
   .boolean('isEven', false)

  v.form('one', '?two', '?isEven')
})

And if we want the one argument to never be by itself? We can use the * (noLone) modifier for that. In the example below, both the two and isEven arguments are optional, but at least one of them must be provided or an error will occur.

const arified = arify(v => {
  v.string('one')
   .number('two', 2)
   .boolean('isEven', false)

  v.form('*one', '?two', '?isEven')
})

So far, so good. But we haven't actually added the function that's going to use these arguments we've configured. That's what the second argument to the arify argument is.

const arified = arify(v => {
  v.string('one', 'hello')
   .number('two', 2)
   .boolean('isEven', false)

  v.form('*one', '?two', '?isEven')
}, (args, rest, form) => {
  // args is an object containing all the arguments by name
  // { one: 'hello', two: 2, isEven: false }

  // rest is an array of any extraneous arguments

  // form is an array representing which form was called
  // ['one', 'two', 'isEven']
})

For the vast majority of use cases, you'll only need args and you can leave rest and form out completely.

What type methods are there?

The following methods should be used within the configuration function as shown below.

const arified = arify(v => {
  // call your type methods here
}, args => {
  console.log('This function receives those arguments')
})

Built-in JS types

type method example
string v.string | v.str coming soon
number v.number | v.num coming soon
boolean v.boolean | v.bln coming soon
Array v.array | v.arr coming soon
Object v.object | v.obj coming soon
Function v.function | v.fun | v.fn coming soon
RegExp v.regExp | v.reg coming soon
Date v.date coming soon
any v.any coming soon

Custom types

type method example
type v.type coming soon
test v.test coming soon
cls v.cls coming soon
match v.match coming soon
add v.add coming soon

That's it for the basics

Click here for the full documentation.

History

arify is based on a previous project called variadic.js. variadic.js was last updated in January of 2014 (2.5 years ago at the time of writing) and since then, a lot has changed. In that time, grunt (variadic's build tool) has fallen out of favor and ES2015 / ES6 usage has risen dramatically. Not only is it supported natively in most environments but even when it isn't, transpilation is too easy to pass up.

While building trilogy I found I was doing a whole lot of argument validation. I toyed with using an API that just accepted a single object containing each argument - simulating named parameters in other languages - but this resulted in super long function declarations and longer-than-necessary function calls because each argument needed the property name in the object. And this still didn't do anything for type-checking or allow for polymorphism (calls with different numbers and types of parameters).

So I came across variadic.js and it provided exactly what I was looking for. But it's had a lack of love for a long time, and I admittedly just wanted to write more ES2015.

Currently, arify is pretty close to a strict rewrite of variadic.js with modern standards. This could change as I come across opportunities for improvement.

variadic.js was already fairly terse, but by rewriting it I was able to:

  • Cut the number of lines by 150-200 thanks to ES2015, along with greatly reduced line lengths in general
  • Add extensive documentation using JSDoc, both inline and generated HTML
  • Remove an awkward jQuery-style prototype aliasing
  • Remove unused utility functions

Similar Projects

Function overloading in JavaScript is clearly a divisive topic. It's a dynamic language so it's not really built for it. Introducing it is not all that popular in terms of having tons of usage, but popular enough that a whole lot of people have built tools to do it. Here are a few I looked at before deciding to add yet another one to the pile by modernizing variadic.js:

Contributing

I am open to input and discussion about the project. Feel free to open an issue or submit a pull request. For large changes, please open an issue to discuss the revisions first.

License

MIT

Based on code also licensed under MIT originally written by @willurd for variadic.js.