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; | |
| } |