Skip to content

Instantly share code, notes, and snippets.

@SlimTim10
Last active October 4, 2018 19:08
Show Gist options
  • Save SlimTim10/f2adbb7310278d493a9fedb039b9e9fd to your computer and use it in GitHub Desktop.
Save SlimTim10/f2adbb7310278d493a9fedb039b9e9fd to your computer and use it in GitHub Desktop.
Poor man's type checking
const ts = require('./type-signatures')
// Without using module
// number -> string -> number
const addNums_ = (n, str) => n + parseInt(str)
// With using module
const addNums = ts('number', 'string')(
(n, str) => n + parseInt(str)
)
// Works because the types match
// console.log(addNums(2, '3'))
// Produces a type error
// console.log(addNums('2', '3'))
// Supports currying
const add = ts('number')(
x => ts('number')(
y => x + y
)
)
// console.log(add(2)(3))
const add3 = add(3)
// console.log(add3('5'))
function test() {
addNums('2', '3')
}
Object.defineProperty(global, '__stack', {
get: function() {
const orig = Error.prepareStackTrace
Error.prepareStackTrace = (_, stack) => stack
const err = new Error
Error.captureStackTrace(err, arguments.callee)
const stack = err.stack
Error.prepareStackTrace = orig
return stack
}
})
const ts = (...types) => f => (...args) => {
if (types.length !== args.length) {
const err = new TypeError('Number of arguments does not match type signature')
return console.error(err.stack)
}
const errs = args
.map((arg, i) => {
const type = types[i]
if (typeof arg !== type) {
const fileName = __stack[3].getFileName()
const lineNumber = __stack[3].getLineNumber()
const columnNumber = __stack[3].getColumnNumber()
const err = new TypeError(`Couldn't match expected type '${type}' with actual type '${typeof arg}'`)
console.error(`at ${fileName}:${lineNumber}:${columnNumber}`)
return err
} else {
return null
}
})
.filter(Boolean)
if (errs.length > 0) {
return errs.forEach(err => console.error(err.stack))
}
return f(...args)
}
module.exports = ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment