Skip to content

Instantly share code, notes, and snippets.

@frostney
Last active October 13, 2015 20:48
Show Gist options
  • Save frostney/4254184 to your computer and use it in GitHub Desktop.
Save frostney/4254184 to your computer and use it in GitHub Desktop.
Chainable type checks in CoffeeScript (Method chaining with type checks) Also allows to wrap type checks into an object, which is a safer option than a switch-case-typeof check AMD definition included :)
do (root = exports ? this) ->
'use strict'
root.check = (variable, checkObject) ->
stringedVar = {}.toString.call variable
typeName = stringedVar.slice(8, stringedVar.length - 1).toLowerCase()
checkType = (typeString, cb, inverse) ->
if inverse
cb?(variable) unless typeName is typeString
else
cb?(variable) if typeName is typeString
###
Else is a reserved keyword, while CoffeeScript interpolates it correctly,
it can only be written as check(...).['else']...
check(...).otherwise(...) is a better choice if using plain JavaScript
###
unless checkObject
result.else = result.otherwise = (cb) -> checkType typeString, cb, !inverse
result
types = (inverse) ->
valid: (cb) ->
if inverse
cb(variable) unless variable?
else
cb(variable) if variable?
@
undefined: (cb) -> checkType "undefined", cb, inverse
null: (cb) -> checkType "null", cb, inverse
string: (cb) -> checkType "string", cb, inverse
number: (cb) -> checkType "number", cb, inverse
object: (cb) -> checkType "object", cb, inverse
array: (cb) -> checkType "array", cb, inverse
function: (cb) -> checkType "function", cb, inverse
if checkObject
typeFuncs = types(false)
for key, value of checkObject
if key.indexOf(',') > -1
keyArray = key.split ','
typeFuncs[k.trim()](value) for k in keyArray
else
typeFuncs[key] value
result = undefined
else
result = types(false)
result.not = types(true)
result
# AMDs are awesome :)
root.define?('check', [], -> root.check) unless exports?
check('test')
.not.string(-> console.log 'not a string')
.else(-> console.log 'Logically, should be a string')
.number((v) -> console.log("its a number with value: #{v}"))
check({})
.object(-> console.log 'Is an object')
.else(-> console.log 'Not an object')
.else(-> console.log 'Maybe an object')
# Instead of using method chaing, you can also use
# a plain object with the type as the key and the value is the callback function
check {},
object: -> console.log 'Is an object'
number: -> console.log 'Is a number'
check 8,
object: -> console.log 'Is an object'
number: -> console.log 'Is a number'
# Multiple keys seperated by a comma also work, just make sure the key is
# written as a key
check 'test',
'string, number': -> console.log 'Either string or number'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment