Last active
October 31, 2016 00:43
-
-
Save BLamy/acb4d6dabc07a1473a48c23fc99377f1 to your computer and use it in GitHub Desktop.
Ramda Where Types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { where, equals, gt, is, pipe, __, curry, tryCatch, either } = require('ramda'); | |
const enforceType = curry((pred, obj) => { | |
if (pred(obj)) return obj; | |
throw new Error(); | |
}); | |
const catchTypeError = tryCatch(__, (err, obj) => void 0); | |
const gaurdedFn = (typePredicate, fn) => catchTypeError( | |
pipe(enforceType(typePredicate), fn) | |
); | |
const userType = where({ | |
firstName: is(String), | |
lastName: is(String), | |
age: is(Number), | |
sex: either(equals('M'), equals('F')) | |
}); | |
const watchVideo = gaurdedFn( | |
userType, | |
curry((user, website) => Object.assign({}, user, { video: website })) | |
); | |
const isAdult = where({ age: gt(__, 18) }); | |
const watchAdultVideo = gaurdedFn( | |
pipe(enforceType(userType), enforceType(isAdult)), | |
curry((user, website) => Object.assign({}, user, { adultVideo: website })) | |
); | |
const renameUser = gaurdedFn( | |
userType, | |
curry((user, firstName, lastName) => Object.assign({}, user, {firstName, lastName})) | |
); | |
const User = function(user) { | |
enforceType(userType, user); | |
this.firstName = user.firstName; | |
this.lastName = user.lastName; | |
this.sex = user.sex; | |
this.age = user.age; | |
this.rename = renameUser(this); | |
this.watchVideo = watchVideo(this); | |
this.watchAdultVideo = watchAdultVideo(this); | |
} | |
const assert = (isTrue, msg) => { if (!isTrue) throw new Error(msg)}; | |
const isNamedFizzbuzz = enforceType(where({ firstName: equals('fizz'), lastName: equals('buzz') })) | |
const isNamedFooBar = enforceType(where({ firstName: equals('foo'), lastName: equals('bar') })) | |
let adult = new User({firstName: 'foo', lastName: 'bar', age: 20, sex: 'F'}); | |
assert(isNamedFooBar(adult), 'Should get default names'); | |
adult = adult.rename("fizz", "buzz") | |
assert(isNamedFizzbuzz(adult), 'Should rename properly'); | |
console.log(adult.watchVideo("youtube")); | |
console.log(adult.watchAdultVideo("pornhub")); | |
const child = new User({firstName: 'foo', lastName: 'bar', age: 11, sex: 'F'}); | |
console.log(child.rename("fizz", "buzz")); | |
console.log(child.watchVideo("youtube")); | |
console.log([ | |
{firstName: 'billy', lastName: 'bob', age: 11, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 17, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 18, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 19, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 99, sex: 'F'} | |
].map(watchVideo).map(fn => fn('youtube.com'))); | |
console.log([ | |
{firstName: 'billy', lastName: 'bob', age: 11, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 17, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 18, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 19, sex: 'F'}, | |
{firstName: 'foo', lastName: 'bar', age: 99, sex: 'F'} | |
].map(watchAdultVideo).map(fn => fn && fn('pornhub.com'))); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment