Skip to content

Commit b799838

Browse files
Merge pull request #24 from Jozty/dev-ch
add functions - propEq, propIs, propSatisfies, eqProps, defaultTo, pathOr, propOr
2 parents d879264 + cee0ff5 commit b799838

16 files changed

+318
-5
lines changed

defaultTo.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Curry2 } from "./utils/types.ts"
2+
import curryN from "./utils/curry_n.ts"
3+
4+
function _defaultTo(defaultV: any, value: any) {
5+
return value == null || value !== value ? defaultV : value;
6+
}
7+
8+
/**
9+
* Returns the second argument if it is not `null`, `undefined` or `NaN`;
10+
* otherwise the first argument is returned.
11+
*
12+
*
13+
* const defaultTo125 = Fae.defaultTo(125)
14+
*
15+
* defaultTo125(null) //=> 125
16+
* defaultTo125(undefined) //=> 125
17+
* defaultTo125(false) //=> false
18+
* defaultTo125('Fae') //=> 'Fae'
19+
*/
20+
export const defaultTo: Curry2<any, any, any> = curryN(2, _defaultTo)

eqProps.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Curry3, Obj } from "./utils/types.ts"
2+
import curryN from "./utils/curry_n.ts"
3+
import { equals } from "./equals.ts"
4+
5+
function _eqProps(prop: string, obj1: Obj, obj2: Obj) {
6+
return equals(obj1[prop], obj2[prop])
7+
}
8+
9+
/**
10+
* Reports whether two objects have the same value, for the specified property.
11+
* Useful as a curried predicate.
12+
*
13+
* const obj1 = { a: 1, b: 2, c: 3, d: 4 }
14+
* const obj2 = { a: 10, b: 20, c: 3, d: 40 }
15+
* Fae.eqProps('a', obj1, obj2) //=> false
16+
* Fae.eqProps('c', obj1, obj2) //=> true
17+
*/
18+
export const eqProps: Curry3<string, Obj, Obj, boolean> = curryN(3, _eqProps)

mod.ts

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export { contains } from './contains.ts'
3535
export { crossProduct } from './crossProduct.ts'
3636
export { curry } from './curry.ts'
3737
export { dec } from './dec.ts'
38+
export { defaultTo } from './defaultTo.ts'
3839
export { dissoc } from './dissoc.ts'
3940
export { dissocPath } from './dissocPath.ts'
4041
export { divide } from './divide.ts'
@@ -45,6 +46,7 @@ export { dropRepeats } from './dropRepeats.ts'
4546
export { dropRepeatsWith } from './dropRepeatsWith.ts'
4647
export { dropWhile } from './dropWhile.ts'
4748
export { endsWith } from './endsWith.ts'
49+
export { eqProps } from './eqProps.ts'
4850
export { equals } from './equals.ts'
4951
export { filter } from './filter.ts'
5052
export { find } from './find.ts'
@@ -81,11 +83,16 @@ export { not } from './not.ts'
8183
export { nth } from './nth.ts'
8284
export { over } from './over.ts'
8385
export { path } from './path.ts'
86+
export { pathOr } from './pathOr.ts'
8487
export { paths, Path } from './paths.ts'
8588
export { pipe } from './pipe.ts'
8689
export { prepend } from './prepend.ts'
8790
export { prop } from './prop.ts'
91+
export { propEq } from './propEq.ts'
92+
export { propIs } from './propIs.ts'
93+
export { propOr } from './propOr.ts'
8894
export { props } from './props.ts'
95+
export { propSatisfies } from './propSatisfies.ts'
8996
export { range } from './range.ts'
9097
export { rangeUntil } from './rangeUntil.ts'
9198
export { reduce } from './reduce.ts'

pathOr.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Curry3, Obj } from "./utils/types.ts"
2+
import curryN from "./utils/curry_n.ts"
3+
import { defaultTo } from './defaultTo.ts'
4+
import { path } from './path.ts'
5+
6+
function _pathOr(d: any, p: Array<any>, obj: any) {
7+
return defaultTo(d, path(p, obj))
8+
}
9+
10+
/**
11+
* If the given, non-null object has a value at the given path, returns the
12+
* value at that path. Otherwise returns the provided default value.
13+
*
14+
*
15+
* Fae.pathOr('N/A', ['a', 'b'], {a: {b: 2}}); //=> 2
16+
* Fae.pathOr('N/A', ['a', 'b'], {c: {b: 2}}); //=> "N/A"
17+
*/
18+
export const pathOr: Curry3<any, Array<any>, any, any> = curryN(3, _pathOr)

propEq.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry3, ObjRec } from "./utils/types.ts"
3+
import { equals } from './equals.ts'
4+
5+
function _propEq(name: string, val: any, obj: ObjRec) {
6+
return equals(val, obj[name])
7+
}
8+
9+
/**
10+
* Returns `true` if the specified object property is equal, to the given value; `false` otherwise.
11+
*
12+
* const shivam = {name: 'shivam', age: 20, hair: 'brown'}
13+
* const shubham = {name: 'shubham', age: 22, hair: 'black'}
14+
* const Krish = {name: 'krish', age: 25, hair: 'black'}
15+
* const students = [shivam, shubham, krish]
16+
* const hasBrownHair = Fae.propEq('hair', 'brown')
17+
* Fae.filter(hasBrownHair, students) //=> [shubham]
18+
*/
19+
export const propEq: Curry3<string, any, ObjRec, boolean> = curryN(3, _propEq)

propIs.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry3, Obj } from "./utils/types.ts"
3+
import { is } from "./utils/is.ts";
4+
5+
function _propIs(type: string, name: string, obj: Obj) {
6+
return is(obj[name], type)
7+
}
8+
9+
/**
10+
* Returns `true` if the specified object property(must be passed as string) is of the given type;
11+
* `false` otherwise.
12+
*
13+
* Fae.propIs('Number', 'a', {a: 1, y: 2}); //=> true
14+
* Fae.propIs('String', 'a', {a: 'foo'}); //=> true
15+
* Fae.propIs('Number', 'a', {}); //=> false
16+
*/
17+
export const propIs: Curry3<string, string, Obj, boolean> = curryN(3, _propIs)

propOr.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry3, Obj, ObjRec } from "./utils/types.ts"
3+
import { pathOr } from "./pathOr.ts"
4+
import { Path } from "./paths.ts"
5+
6+
function _propOr(val: any, p: Path, obj: ObjRec | null) {
7+
return pathOr(val, [p], obj)
8+
}
9+
10+
/**
11+
* If the given, non-null object has an own property with the specified name,
12+
* returns the value of that property. Otherwise returns the provided default
13+
* value.
14+
* const alice = {
15+
* name: 'Fae',
16+
* age: 15
17+
* };
18+
* const Great = Fae.prop('GreatLibrary');
19+
* const GreatWithDefault = Fae.propOr('FaeModule', 'GreatLibrary');
20+
*
21+
* Great(Fae); //=> undefined
22+
* GreatWithDefault(Fae); //=> 'FaeModule'
23+
*/
24+
export const propOr: Curry3<any, Path, ObjRec | null, any> = curryN(3, _propOr)

propSatisfies.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ObjRec, Predicate1, Curry3 } from "./utils/types.ts"
2+
import curryN from "./utils/curry_n.ts"
3+
4+
function _propSatisfies(pred: Predicate1, name: string, obj: ObjRec) {
5+
return pred(obj[name]);
6+
}
7+
8+
/**
9+
* Returns `true` if the specified object property satisfies the given
10+
* predicate; `false` otherwise.
11+
*
12+
* Fae.propSatisfies(x => x > 0, 'x', {x: 1, y: 2}); //=> true
13+
*/
14+
export const propSatisfies: Curry3<Predicate1, string, ObjRec, boolean> = curryN(3, _propSatisfies)

specs/PropEq.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { propEq } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('propEq', () => {
6+
7+
let obj1 = {name: 'shubham', age: 22, hair: 'blue'}
8+
let obj2 = {name: 'Shivam', age: 21, hair: 'black'}
9+
10+
it('should determine property matching a given value for a specific object properly', () => {
11+
eq(propEq('name', 'shubham', obj1), true)
12+
eq(propEq('hair', 'black', obj2), true)
13+
eq(propEq('hair', 'blue', obj2), false)
14+
})
15+
16+
})

specs/defaultTo.spec.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { defaultTo } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('defaultTo', () => {
6+
7+
let defaultTo125 = defaultTo(125)
8+
9+
it('should return the default value if input is null, undefined or NaN', () => {
10+
eq(125, defaultTo125(null))
11+
eq(125, defaultTo125(undefined))
12+
eq(125, defaultTo125(NaN))
13+
})
14+
15+
it('should return the input value if it is not null/undefined', () => {
16+
eq('a real value', defaultTo125('a real value'))
17+
})
18+
19+
it('should return the input value even if it is considered falsy', () => {
20+
eq('', defaultTo125(''))
21+
eq(0, defaultTo125(0))
22+
eq(false, defaultTo125(false))
23+
eq([], defaultTo125([]))
24+
})
25+
26+
it('should be called with both arguments directly', () => {
27+
eq(125, defaultTo(125, null))
28+
eq('a real value', defaultTo(125, 'a real value'))
29+
})
30+
31+
})

specs/eqProps.spec.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { eqProps } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('eqProps', () => {
6+
7+
it('should return true when two objects have the same value for a given property', () => {
8+
eq(eqProps('name', {name: 'shubham', age: 10}, {name: 'shubham', age: 12}), true)
9+
eq(eqProps('name', {name: 'shivam', age: 10}, {name: 'shubham', age: 10}), false)
10+
eq(eqProps('value', {value: 0}, {value: -0}), false)
11+
eq(eqProps('value', {value: -0}, {value: 0}), false)
12+
eq(eqProps('value', {value: NaN}, {value: NaN}), true)
13+
})
14+
15+
})

specs/not.spec.ts

-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ import { describe, it, expect } from "./_describe.ts"
22
import { not } from '../mod.ts'
33
import { eq } from "./utils/utils.ts"
44

5-
/**
6-
* @function
7-
* takes an argument and returns its not
8-
*/
9-
105
describe('not', () => {
116
it('should be properly declared',() => {
127
eq(not(true), false)

specs/pathOr.spec.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { pathOr } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('pathOr', () => {
6+
7+
let deepObject = {a: {b: {c: 'c'}}, falseVal: false, nullVal: null, undefinedVal: undefined, arrayVal: ['arr']}
8+
9+
it('should take a path and an object and returns the value at the path or the default value', () => {
10+
let obj = {
11+
a: {
12+
b: {
13+
c: 100,
14+
d: 200
15+
},
16+
e: {
17+
f: [100, 101, 102],
18+
g: 'G'
19+
},
20+
h: 'H'
21+
},
22+
i: 'I',
23+
j: ['J']
24+
}
25+
eq(pathOr('Unknown', ['a', 'b', 'c'], obj), 100)
26+
eq(pathOr('Unknown', [], obj), obj)
27+
eq(pathOr('Unknown', ['a', 'e', 'f', 1], obj), 101)
28+
eq(pathOr('Unknown', ['j', 0], obj), 'J')
29+
eq(pathOr('Unknown', ['j', 1], obj), 'Unknown')
30+
eq(pathOr('Unknown', ['a', 'b', 'c'], null), 'Unknown')
31+
})
32+
33+
it("should get a deep property's value from objects", () => {
34+
eq(pathOr('Unknown', ['a', 'b', 'c'], deepObject), 'c')
35+
eq(pathOr('Unknown', ['a'], deepObject), deepObject.a)
36+
})
37+
38+
it('should return the default value for items not found', () => {
39+
eq(pathOr('Unknown', ['a', 'b', 'foo'], deepObject), 'Unknown')
40+
eq(pathOr('Unknown', ['bar'], deepObject), 'Unknown')
41+
})
42+
43+
it('should return the default value for null/undefined', () => {
44+
eq(pathOr('Unknown', ['toString'], null), 'Unknown')
45+
eq(pathOr('Unknown', ['toString'], undefined), 'Unknown')
46+
})
47+
48+
it('should work with falsy items', () => {
49+
eq(pathOr('Unknown', ['toString'], false), Boolean.prototype.toString)
50+
})
51+
52+
})

specs/propIs.spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { propIs } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('propIs', () => {
6+
7+
it('should return true if the specified object property is of the given type', () => {
8+
eq(propIs('Number', 'a', {a: 1, y: 2}), true)
9+
eq(propIs('String', 'a', {a: 'foo'}), true)
10+
eq(propIs('Number', 'a', {}), false)
11+
})
12+
13+
it('Should return false otherwise', () => {
14+
eq(propIs('String', 'ob', {ob: 1}), false)
15+
eq(propIs('String', 'ob', {}), false)
16+
})
17+
18+
})

specs/propOr.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { propOr } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
6+
describe('propOr', () => {
7+
8+
let shubham = {name: 'shubham', age: 23}
9+
let shivam = {age: 99}
10+
11+
let num = propOr('Unknown', 'name')
12+
13+
it('should return a function that fetches the appropriate property', () => {
14+
eq(typeof num, 'function')
15+
eq(num(shubham), 'shubham')
16+
})
17+
18+
it('should return the default value when the property does not exist', () => {
19+
eq(num(shivam), 'Unknown')
20+
})
21+
22+
it('should return the default value when the object is nil', () => {
23+
eq(num(null), 'Unknown')
24+
eq(num(void 0), 'Unknown')
25+
})
26+
27+
it('should use the default when supplied an object with a nil value', () => {
28+
eq(propOr('foo', 'x', {x: null}), 'foo')
29+
eq(propOr('foo', 'x', {x: undefined}), 'foo')
30+
})
31+
32+
})

specs/propSatisfies.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { describe, it} from "./_describe.ts"
2+
import { propSatisfies } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('propSatisfies', () => {
6+
7+
let isPositive = (n: number) => n > 0
8+
9+
it('should return true if the specified object property satisfies the given predicate', () => {
10+
eq(propSatisfies(isPositive, 'x', {x: 1, y: 0}), true)
11+
})
12+
13+
it('should return false otherwise', () => {
14+
eq(propSatisfies(isPositive, 'y', {x: 1, y: 0}), false)
15+
})
16+
17+
})

0 commit comments

Comments
 (0)