npm package: @sa0001/fn-typer
Description: [NPM][https://www.npmjs.com/package/@sa0001/fn-typer]
Author: sa0001
Latest version: 0.0.3

# @sa0001/fn-typer

[NPM][https://www.npmjs.com/package/@sa0001/fn-typer]

A simple wrapper which adds run-time type checking to function arguments and return value, using a very terse syntax.

The schema of a function contains one or more comma-separated argument types (optional), then '->' (required), then a return value type (optional).

> (see section "Usage -> Schema Examples")

Any valid type may be used; the value's type is determined using `@sa0001/type-of`.  The only exception is `integer`, which is not a real type but was added for convenience, and requires a whole number.

The most common types have short aliases, to make function schemas very compact.

> (see section "Usage -> Alias Examples")

## Install

```bash
npm install @sa0001/fn-typer
```

## Usage

```javascript
const fnTyper = require('@sa0001/fn-typer')

export const add = fnTyper('n, n -> n', function(a, b) {
	return a + b
})

export const concat = fnTyper('s, s -> s', function(a, b) {
	return a + b
})

export const repeat = fnTyper('string, integer -> string', function(text, count) {
	let result = ''
	for (let i = 0; i < count; i++) {
		result += text
	}
	return result
})
```

### Schema Examples

```javascript
// arguments and return value:
wrappedFn = fnTyper('number, string, object -> string', ()=>{})
// only arguments:
wrappedFn = fnTyper('number, string, object ->', ()=>{})
// only return value:
wrappedFn = fnTyper('-> string', ()=>{})
// optional arguments (may be null or undefined):
wrappedFn = fnTyper('number?, string?, object? -> array?', ()=>{})
// multiple types:
wrappedFn = fnTyper('number/string?, array/object? -> boolean', ()=>{})
// any type (ecluding null/undefined)
wrappedFn = fnTyper('* -> *', ()=>{})
wrappedFn = fnTyper('any -> any', ()=>{})
// any type (including null/undefined)
wrappedFn = fnTyper('*? -> *?', ()=>{})
wrappedFn = fnTyper('any? -> any?', ()=>{})
```

### Alias Examples

```javascript
// short aliases:
fnTyper('a, b, d, e, f, i, n, o, p, r, s -> *', ()=>{})
// is the same as:
fnTyper('array, boolean, date, error, function, integer, number, object, promise, regexp, string -> any', ()=>{})
```

### Other Examples


```javascript
// simple examples
const lib = {
	
	add: fnTyper('n, n -> n', (a, b) => {
		return a + b
	}),
	
	concat: fnTyper('s, s -> s', (a, b) => {
		return a + b
	}),
	
}

lib.add('a', 'b') // Error: fnType(add): argument 1 requires type 'number' but has type 'string'
lib.concat(12, 34) // Error: fnType(concat): argument 1 requires type 'string' but has type 'number'

// complex example
const get_user_name = fnTyper('n, s?, o? -> s?', (user_id, prefix, options = {}) => {
	_.defaults(options, {
		separator: ' ',
	})
	
	user_name = Db.select('select user_name from users where id = ?', user_id)[0].user_name
	
	if (!user_name) {
		return
	}
	
	if (prefix) {
		user_name = prefix + separator + user_name
	}
	
	return user_name
})

get_user_name() // Error: fnTyper(get_user_name): there are 1 required arguments but only 0 arguments provided
get_user_name(1, false) // Error: fnTyper(get_user_name): argument 2 requires type 'string?' but has type 'boolean'
```

## Todo

- add spread syntax: `string?...`

## License

[MIT](http://vjpr.mit-license.org)