Skip to content

Commit

Permalink
feat: add isNonPositive, isNonNegative (#434)
Browse files Browse the repository at this point in the history
 - clarify zero exclusion for isPositive, isNegative

Closes #324
  • Loading branch information
Undistraction authored and char0n committed Mar 14, 2018
1 parent 274d5ad commit 8d62dc1
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 35 deletions.
81 changes: 48 additions & 33 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,15 +251,29 @@ declare namespace RamdaAdjunct {
isNotNumber(val: any): boolean;

/**
* Checks if value is a positive `Number` primitive or object.
* Checks if value is a positive `Number` primitive or object. Zero is considered neither
* positive or negative.
*/
isPositive(val: any): val is number;

/**
* Checks if value is a negative `Number` primitive or object.
* Checks if value is a negative `Number` primitive or object. Zero is considered neither
* positive or negative.
*/
isNegative(val: any): val is number;

/**
* Checks if value is a non-positive `Number` primitive or object. This includes all
* negative numbers and zero.
*/
isNonPositive(val: any): val is number;

/**
* Checks if value is a non-negative `Number` primitive or object. This includes all
* positive numbers and zero.
*/
isNonNegative(val: any): val is number;

/**
* Checks whether the passed value is a finite `Number`.
*/
Expand Down Expand Up @@ -426,18 +440,18 @@ declare namespace RamdaAdjunct {
* will be called with the left value.
*/
cata<V1, V2, T1, T2>(
leftFn: (leftValue: V1) => T1,
rightFn: (rightValue: V2) => T2,
either: Catamorphism<V1|V2>,
): T1|T2;
leftFn: (leftValue: V1) => T1,
rightFn: (rightValue: V2) => T2,
either: Catamorphism<V1 | V2>,
): T1 | T2;
cata<V1, V2, T1, T2>(
leftFn: (leftValue: V1) => T1,
rightFn: (rightValue: V2) => T2):
(either: Catamorphism<V1|V2>,
) => T1|T2;
leftFn: (leftValue: V1) => T1,
rightFn: (rightValue: V2) => T2):
(either: Catamorphism<V1 | V2>,
) => T1 | T2;
cata<V1, V2, T1, T2>(leftFn: (leftValue: V1) => T1): {
(rightFn: (rightValue: V2) => T1, either: Catamorphism<V1|V2>): T1|T2;
(rightFn: (rightValue: V2) => T1): (either: Catamorphism<V1|V2>) => T1|T2
(rightFn: (rightValue: V2) => T1, either: Catamorphism<V1 | V2>): T1 | T2;
(rightFn: (rightValue: V2) => T1): (either: Catamorphism<V1 | V2>) => T1 | T2
};

/**
Expand Down Expand Up @@ -575,7 +589,7 @@ declare namespace RamdaAdjunct {
): {
(acc: TResult): (list: R) => TResult;
(acc: TResult, list: R): TResult
};
};

/**
* Given an `Iterable`(arrays are `Iterable`), or a promise of an `Iterable`,
Expand Down Expand Up @@ -667,9 +681,9 @@ declare namespace RamdaAdjunct {
* Returns true if the specified object property is not equal,
* in R.equals terms, to the given value; false otherwise.
*/
propNotEq(prop: string|number, value: any, obj: object): boolean;
propNotEq(prop: string|number, value: any): (obj: object) => boolean;
propNotEq(prop: string|number): {
propNotEq(prop: string | number, value: any, obj: object): boolean;
propNotEq(prop: string | number, value: any): (obj: object) => boolean;
propNotEq(prop: string | number): {
(value: any, obj: object): boolean;
(value: any): (obj: object) => boolean;
};
Expand All @@ -678,42 +692,42 @@ declare namespace RamdaAdjunct {
* Determines whether a nested path on an object doesn't have a specific value,
* in R.equals terms. Most likely used to filter a list.
*/
pathNotEq(path: Array<string|number>, value: any, obj: object): boolean;
pathNotEq(path: Array<string|number>, value: any): (obj: object) => boolean;
pathNotEq(path: Array<string|number>): {
pathNotEq(path: Array<string | number>, value: any, obj: object): boolean;
pathNotEq(path: Array<string | number>, value: any): (obj: object) => boolean;
pathNotEq(path: Array<string | number>): {
(value: any, obj: object): boolean;
(value: any): (obj: object) => boolean;
};

/**
* Returns whether or not an object has an own property with the specified name at a given path.
*/
hasPath(path: Array<string|number>, obj: object): boolean;
hasPath(path: Array<string|number>): (obj: object) => boolean;
hasPath(path: Array<string | number>, obj: object): boolean;
hasPath(path: Array<string | number>): (obj: object) => boolean;

/**
* Spreads object under property path onto provided object.
*/
spreadPath(path: Array<string|number>, obj: object): object;
spreadPath(path: Array<string|number>): (obj: object) => object;
spreadPath(path: Array<string | number>, obj: object): object;
spreadPath(path: Array<string | number>): (obj: object) => object;

/**
* Spreads object under property onto provided object.
*/
spreadProp(prop: string|number, obj: object): object;
spreadProp(prop: string|number): (obj: object) => object;
spreadProp(prop: string | number, obj: object): object;
spreadProp(prop: string | number): (obj: object) => object;

/**
* Flattens a property path so that its fields are spread out into the provided object.
*/
flattenPath(path: Array<string|number>, obj: object): object;
flattenPath(path: Array<string|number>): (obj: object) => object;
flattenPath(path: Array<string | number>, obj: object): object;
flattenPath(path: Array<string | number>): (obj: object) => object;

/**
* Flattens a property so that its fields are spread out into the provided object.
*/
flattenProp(prop: string|number, obj: object): object;
flattenProp(prop: string|number): (obj: object) => object;
flattenProp(prop: string | number, obj: object): object;
flattenProp(prop: string | number): (obj: object) => object;

/**
* Composable shortcut for `Promise.all`.
Expand Down Expand Up @@ -754,16 +768,17 @@ declare namespace RamdaAdjunct {
* from fromIndex (inclusive).
* Dispatches to the slice method of the third argument, if present.
*/
sliceFrom<T>(fromIndex: number, list: string|T[]): string|T[];
sliceFrom(fromIndex: number): <T>(list: string|T[]) => string|T[];
sliceFrom<T>(fromIndex: number, list: string | T[]): string | T[];
sliceFrom(fromIndex: number): <T>(list: string | T[]) => string | T[];
sliceFrom<T>(fromIndex: number, list: string | T[]): string | T[];

/**
* Returns the elements of the given list or string (or object with a slice method)
* to toIndex (exclusive).
* Dispatches to the slice method of the second argument, if present.
*/
sliceTo<T>(toIndex: number, list: string|T[]): string|T[];
sliceTo(toIndex: number): <T>(list: string|T[]) => string|T[];
sliceTo<T>(toIndex: number, list: string | T[]): string | T[];
sliceTo(toIndex: number): <T>(list: string | T[]) => string | T[];

/**
* Returns a partial copy of an array omitting the indexes specified.
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export { default as isNumber } from './isNumber';
export { default as isNotNumber } from './isNotNumber';
export { default as isPositive } from './isPositive';
export { default as isNegative } from './isNegative';
export { default as isNonPositive } from './isNonPositive';
export { default as isNonNegative } from './isNonNegative';
export { default as isNaN } from './isNaN';
export { default as isNotNaN } from './isNotNaN';
export { default as isFinite } from './isFinite';
Expand Down
3 changes: 2 additions & 1 deletion src/isNegative.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { both, gt } from 'ramda';
import isNumber from './isNumber';

/**
* Checks if value is a negative `Number` primitive or object.
* Checks if value is a negative `Number` primitive or object. Zero is not considered neither
* positive or negative.
*
* @func isNegative
* @memberOf RA
Expand Down
30 changes: 30 additions & 0 deletions src/isNonNegative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { both, gte, flip } from 'ramda';

import isNumber from './isNumber';

/**
* Checks if value is a non-negative `Number` primitive or object. This includes all positive
* numbers and zero.
*
* @func isNonNegative
* @memberOf RA
* @since {@link https://char0n.github.io/ramda-adjunct/2.6.0|v2.6.0}
* @category Type
* @sig * -> Boolean
* @param {*} val The value to test
* @return {boolean}
* @see {@link RA.isPositive|isPositive}, {@link RA.isNonPositive|isNonPositive}
* @example
*
* RA.isNonNegative(0); // => true
* RA.isNonNegative(1); // => true
* RA.isNonNegative(Infinity); // => true
* RA.isNonNegative(Number.MAX_VALUE); // => true
*
* RA.isNonNegative(-Infinity); // => false
* RA.isNonNegative(Number.MIN_VALUE); // => false
* RA.isNonNegative(NaN); // => false
*/
const isNonNegative = both(isNumber, flip(gte)(0));

export default isNonNegative;
30 changes: 30 additions & 0 deletions src/isNonPositive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { both, lte, flip } from 'ramda';

import isNumber from './isNumber';

/**
* Checks if value is a non-positive `Number` primitive or object. This includes all negative
* numbers and zero.
*
* @func isNonPositive
* @memberOf RA
* @since {@link https://char0n.github.io/ramda-adjunct/2.6.0|v2.6.0}
* @category Type
* @sig * -> Boolean
* @param {*} val The value to test
* @return {Boolean}
* @see {@link RA.isNegative|isNegative}, {@link RA.isNonNegative|isNonNegative}
* @example
*
* RA.isNonPositive(0); // => true
* RA.isNonPositive(-1); // => true
* RA.isNonPositive(-Infinity); // => true
* RA.isNonPositive(Number.MIN_VALUE); // => true
*
* RA.isNonPositive(Infinity); // => false
* RA.isNonPositive(Number.MAX_VALUE); // => false
* RA.isNonPositive(NaN); // => false
*/
const isNonPositive = both(isNumber, flip(lte)(0));

export default isNonPositive;
2 changes: 1 addition & 1 deletion src/isPositive.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { both, lt } from 'ramda';
import isNumber from './isNumber';

/**
* Checks if value is a positive `Number` primitive or object.
* Checks if value is a positive `Number` primitive or object. Zero is not considered positive.
*
* @func isPositive
* @memberOf RA
Expand Down
42 changes: 42 additions & 0 deletions test/isNonNegative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as RA from '../src/index';
import MAX_SAFE_INTEGER from '../src/internal/polyfills/Number.MAX_SAFE_INTEGER';
import MIN_SAFE_INTEGER from '../src/internal/polyfills/Number.MIN_SAFE_INTEGER';
import eq from './shared/eq';
import args from './shared/arguments';
import Symbol from './shared/Symbol';

describe('isNonNegative', function() {
it('tests a value for non-negative `Number`', function() {
eq(RA.isNonNegative(0), true);
eq(RA.isNonNegative(-0.1), false);
eq(RA.isNonNegative(0.1), true);
eq(RA.isNonNegative(Object(0)), true);
eq(RA.isNonNegative(Object(-0.1)), false);
eq(RA.isNonNegative(Object(0.1)), true);
eq(RA.isNonNegative(NaN), false);
eq(RA.isNonNegative(Infinity), true);
eq(RA.isNonNegative(-Infinity), false);
eq(RA.isNonNegative(MAX_SAFE_INTEGER), true);
eq(RA.isNonNegative(MIN_SAFE_INTEGER), false);
eq(RA.isNonNegative(Number.MAX_VALUE), true);
eq(RA.isNonNegative(Number.MIN_VALUE), true);

eq(RA.isNonNegative(new Date()), false);
eq(RA.isNonNegative(args), false);
eq(RA.isNonNegative([1, 2, 3]), false);
eq(RA.isNonNegative(Object(false)), false);
eq(RA.isNonNegative(new Error()), false);
eq(RA.isNonNegative(RA), false);
eq(RA.isNonNegative(Array.prototype.slice), false);
eq(RA.isNonNegative({ a: 1 }), false);
eq(RA.isNonNegative(/x/), false);
eq(RA.isNonNegative(Object('a')), false);

if (Symbol !== 'undefined') {
eq(RA.isNonNegative(Symbol), false);
}

eq(RA.isNonNegative(null), false);
eq(RA.isNonNegative(undefined), false);
});
});
42 changes: 42 additions & 0 deletions test/isNonPositive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as RA from '../src/index';
import MAX_SAFE_INTEGER from '../src/internal/polyfills/Number.MAX_SAFE_INTEGER';
import MIN_SAFE_INTEGER from '../src/internal/polyfills/Number.MIN_SAFE_INTEGER';
import eq from './shared/eq';
import args from './shared/arguments';
import Symbol from './shared/Symbol';

describe('isNonPositive', function() {
it('tests a value for non-positive `Number`', function() {
eq(RA.isNonPositive(0), true);
eq(RA.isNonPositive(-0.1), true);
eq(RA.isNonPositive(0.1), false);
eq(RA.isNonPositive(Object(0)), true);
eq(RA.isNonPositive(Object(-0.1)), true);
eq(RA.isNonPositive(Object(0.1)), false);
eq(RA.isNonPositive(NaN), false);
eq(RA.isNonPositive(Infinity), false);
eq(RA.isNonPositive(-Infinity), true);
eq(RA.isNonPositive(MAX_SAFE_INTEGER), false);
eq(RA.isNonPositive(MIN_SAFE_INTEGER), true);
eq(RA.isNonPositive(Number.MAX_VALUE), false);
eq(RA.isNonPositive(Number.MIN_VALUE), false);

eq(RA.isNonPositive(new Date()), false);
eq(RA.isNonPositive(args), false);
eq(RA.isNonPositive([1, 2, 3]), false);
eq(RA.isNonPositive(Object(false)), false);
eq(RA.isNonPositive(new Error()), false);
eq(RA.isNonPositive(RA), false);
eq(RA.isNonPositive(Array.prototype.slice), false);
eq(RA.isNonPositive({ a: 1 }), false);
eq(RA.isNonPositive(/x/), false);
eq(RA.isNonPositive(Object('a')), false);

if (Symbol !== 'undefined') {
eq(RA.isNonPositive(Symbol), false);
}

eq(RA.isNonPositive(null), false);
eq(RA.isNonPositive(undefined), false);
});
});

0 comments on commit 8d62dc1

Please sign in to comment.