Skip to content

Commit

Permalink
feat(micro-dash): add negate()
Browse files Browse the repository at this point in the history
Closes #26
  • Loading branch information
ersimont committed Feb 3, 2021
1 parent 74dbdbf commit 1056836
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 0 deletions.
4 changes: 4 additions & 0 deletions projects/micro-dash-sizes/src/app/function/negate.lodash.ts
@@ -0,0 +1,4 @@
import negate from 'lodash-es/negate';

const isNotArray = negate(Array.isArray);
console.log(isNotArray(0), isNotArray([]));
@@ -0,0 +1,4 @@
import { negate } from '@s-libs/micro-dash';

const isNotArray = negate(Array.isArray);
console.log(isNotArray(0), isNotArray([]));
1 change: 1 addition & 0 deletions projects/micro-dash/src/lib/function/index.ts
Expand Up @@ -2,6 +2,7 @@ export { bindKey } from './bind-key';
export { curry } from './curry';
export { debounce } from './debounce';
export { memoize } from './memoize';
export { negate } from './negate';
export { once } from './once';
export { partial } from './partial';
export { throttle } from './throttle';
68 changes: 68 additions & 0 deletions projects/micro-dash/src/lib/function/negate.spec.ts
@@ -0,0 +1,68 @@
import { expectSingleCallAndReset } from '@s-libs/ng-dev';
import { bind } from 'lodash-es';
import { negate } from './negate';

describe('negate()', () => {
function isEven(n: number): boolean {
return n % 2 === 0;
}

//
// stolen from https://github.com/lodash/lodash
//

it('should create a function that negates the result of `func`', () => {
const negated = negate(isEven);

expect(negated(1)).toBe(true);
expect(negated(2)).toBe(false);
});

it('should create a function that negates the result of `func`', () => {
const negated = negate(isEven);

expect(negated(1)).toBe(true);
expect(negated(2)).toBe(false);
});

it('should create a function that accepts multiple arguments', () => {
const spy = jasmine.createSpy();
const negated = negate(spy);

negated();
expectSingleCallAndReset(spy);

negated(1);
expectSingleCallAndReset(spy, 1);

negated(1, 2);
expectSingleCallAndReset(spy, 1, 2);

negated(1, 2, 3);
expectSingleCallAndReset(spy, 1, 2, 3);

negated(1, 2, 3, 4);
expectSingleCallAndReset(spy, 1, 2, 3, 4);
});

it('should use `this` binding of function', () => {
const fn = function (this: any): boolean {
return this.a;
};
const object: any = { a: 1 };

let negated = negate(bind(fn, object));
expect(negated()).toBe(false);

negated = bind(negate(fn), object);
expect(negated()).toBe(false);

object.wrapper = negate(fn);
expect(object.wrapper()).toBe(false);

const spy = jasmine.createSpy();
object.spied = negate(spy);
object.spied();
expect(spy.calls.mostRecent().object).toBe(object);
});
});
14 changes: 14 additions & 0 deletions projects/micro-dash/src/lib/function/negate.ts
@@ -0,0 +1,14 @@
/**
* Creates a function that negates the result of the predicate `func`. The `func` predicate is invoked with the `this` binding and arguments of the created function.
*
* Contribution to minified bundle size, when it is the only function imported:
* - Lodash: 342 bytes
* - Micro-dash: 97 bytes
*/
export function negate<F extends (...args: any[]) => any>(
predicate: F,
): (this: ThisParameterType<F>, ...args: Parameters<F>) => boolean {
return function (this: any, ...args): boolean {
return !predicate.apply(this, args);
} as F;
}
13 changes: 13 additions & 0 deletions projects/micro-dash/src/typing-tests/function/negate.dts-spec.ts
@@ -0,0 +1,13 @@
import { negate } from '../../lib/function';

// $ExpectType (this: unknown, arg: any) => boolean
negate(Array.isArray);

declare const boundFn: (
this: Date,
arg1: string,
arg2: 'hi',
...rest: number[]
) => Date;
// $ExpectType (this: Date, arg1: string, arg2: "hi", ...rest: number[]) => boolean
negate(boundFn);

0 comments on commit 1056836

Please sign in to comment.