Skip to content

Commit

Permalink
add S.props
Browse files Browse the repository at this point in the history
  • Loading branch information
svozza authored and davidchambers committed Dec 30, 2016
1 parent 01f053e commit 0b0ac77
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 4 deletions.
30 changes: 26 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2787,6 +2787,29 @@
}
S.prop = def('prop', {a: [Accessible]}, [$.String, a, b], prop);

//# props :: Accessible a => Array String -> a -> b
//.
//. Takes a property path (an array of property names) and an object with
//. known structure and returns the value at the given path. If for some
//. reason the path does not exist, a type error is thrown.
//.
//. For accessing property paths of uncertain objects, use [`gets`](#gets)
//. instead.
//.
//. ```javascript
//. > S.props(['a', 'b', 'c'], {a: {b: {c: 1}}})
//. 1
//. ```
function props(path, obj) {
return path.reduce(function(memo, key) {
if (key in memo) return memo[key];
throw new TypeError('‘props’ expected object to have a property at ' +
R.toString(path) + '; ' +
R.toString(obj) + ' does not');
}, Object(obj));
}
S.props = def('props', {a: [Accessible]}, [$.Array($.String), a, b], props);

//# get :: Accessible a => (b -> Boolean) -> String -> a -> Maybe c
//.
//. Takes a predicate, a property name, and an object and returns Just the
Expand Down Expand Up @@ -2814,10 +2837,9 @@

//# gets :: Accessible a => (b -> Boolean) -> Array String -> a -> Maybe c
//.
//. Takes a predicate, an array of property names, and an object and returns
//. Just the value at the path specified by the array of property names if
//. such a path exists and the value satisfies the given predicate; Nothing
//. otherwise.
//. Takes a predicate, a property path (an array of property names), and
//. an object and returns Just the value at the given path if such a path
//. exists and the value satisfies the given predicate; Nothing otherwise.
//.
//. See also [`get`](#get).
//.
Expand Down
70 changes: 70 additions & 0 deletions test/props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict';

var S = require('..');

var eq = require('./internal/eq');
var throws = require('./internal/throws');


test('props', function() {

eq(typeof S.props, 'function');
eq(S.props.length, 2);

throws(function() { S.props(1); },
TypeError,
'Invalid value\n' +
'\n' +
'props :: Accessible a => Array String -> a -> b\n' +
' ^^^^^^^^^^^^\n' +
' 1\n' +
'\n' +
'1) 1 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' +
'\n' +
'The value at position 1 is not a member of ‘Array String’.\n');

throws(function() { S.props(['a', 'b', 'c'], null); },
TypeError,
'Type-class constraint violation\n' +
'\n' +
'props :: Accessible a => Array String -> a -> b\n' +
' ^^^^^^^^^^^^ ^\n' +
' 1\n' +
'\n' +
'1) null :: Null\n' +
'\n' +
'‘props’ requires ‘a’ to satisfy the Accessible type-class constraint; the value at position 1 does not.\n');

throws(function() { S.props([true, false], {a: {b: {c: 1}}}); },
TypeError,
'Invalid value\n' +
'\n' +
'props :: Accessible a => Array String -> a -> b\n' +
' ^^^^^^\n' +
' 1\n' +
'\n' +
'1) true :: Boolean\n' +
'\n' +
'The value at position 1 is not a member of ‘String’.\n');

throws(function() { S.props(['a', 'b', 'c'], true); },
TypeError,
'‘props’ expected object to have a property at ["a", "b", "c"]; true does not');

throws(function() { S.props(['a', 'b', 'c'], 1); },
TypeError,
'‘props’ expected object to have a property at ["a", "b", "c"]; 1 does not');

throws(function() { S.props(['a', 'b', 'd'], {a: {b: {c: 1}}}); },
TypeError,
'‘props’ expected object to have a property at ["a", "b", "d"]; {"a": {"b": {"c": 1}}} does not');

throws(function() { S.props(['a', 'b', 'c'], [1, 2, 3]); },
TypeError,
'‘props’ expected object to have a property at ["a", "b", "c"]; [1, 2, 3] does not');

eq(S.props(['a', 'b', 'c'], {a: {b: {c: 1}}}), 1);
eq(S.props(['a', 'b', 'c', '0'], {a: {b: {c: [2, 4, 6]}}}), 2);
eq(S.props(['a', 'b', 'c'], Object.create({a: {b: {c: 1}}})), 1);

});

0 comments on commit 0b0ac77

Please sign in to comment.