Utility function to create overloaded functions
- Start in usage.js and follow the imports
- Userland interesting stuff can be found in factories.js
- usage.js for examples of… usages
import overload from './overload'; | |
import User from './user'; | |
const createUser = overload({ | |
'array': (master) => ([firstName, lastName]) => master({firstName, lastName}), | |
'object': () => (userProperties) => new User(userProperties), | |
'string, string': (master) => (firstName, lastName) => master({firstName, lastName}), | |
}); | |
export { | |
createUser, | |
}; |
/* | |
- Takes implementations as an object, each key/value is an implementation | |
- An implementation is: | |
key = signature as string | |
value = implementation as hoc function that provides a proxy function (called "master" in this example) | |
*/ | |
import typeIs from './type-is'; | |
export default overload; | |
function overload(implementations) { | |
const cache = {}; | |
Object.keys(implementations).forEach((signature) => { | |
cache[signature.replace(/ /g, '')] = implementations[signature]; | |
}); | |
return function master(...args) { | |
const signature = args.map((arg) => typeIs(arg)).join(','); | |
const implementation = cache[signature]; | |
if (typeof implementation !== 'function') { | |
throw new TypeError(`No such signature: ${signature}`); | |
} | |
return implementation(master).apply(this, args); | |
}; | |
} |
// A better typeof | |
export default typeIs; | |
function typeIs(value) { | |
if (Array.isArray(value)) { | |
return 'array'; | |
} | |
if (value === null) { | |
return 'null'; | |
} | |
const type = typeof value; | |
return type === 'object' ? getObjectType(value) || type : type; | |
} | |
const internalClassToTypeMap = { | |
'[object Boolean]': typeof true, | |
'[object Date]': 'date', | |
'[object Number]': typeof 0, | |
'[object String]': typeof '', | |
// add more at your discretion | |
}; | |
function getObjectType(value) { | |
const internalClass = Object.prototype.toString.call(value); | |
return internalClassToTypeMap[internalClass]; | |
} |
import {createUser} from './factories'; | |
const jane = createUser({ | |
firstName: 'Jane', | |
lastName: 'Doe', | |
}); | |
const john = createUser('John', 'Doe'); | |
const anotherJohn = createUser(['John', 'Doe']); |
export default User; | |
function User({firstName, lastName}) { | |
this.firstName = firstName; | |
this.lastName = lastName; | |
} |