Repository: char0n/ramda-adjunct
Pull request #1554 (2020-08-05 12:47:33)

invoke
[#81](https://github.com/char0n/ramda-adjunct/issues/81)


Patch:
diff --git a/src/index.js b/src/index.js
index 40c86139e5..de88db5f8d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -158,6 +158,7 @@ export { default as sortByProps } from './sortByProps';
 export { default as skipTake } from './skipTake';
 export { default as rangeStep } from './rangeStep';
 // Object
+export { default as invoke } from './invoke';
 export { default as invokeArgs } from './invokeArgs';
 export { default as paths } from './paths';
 export { default as renameKeys } from './renameKeys';
diff --git a/src/invoke.js b/src/invoke.js
new file mode 100644
index 0000000000..c12de9ebd0
--- /dev/null
+++ b/src/invoke.js
@@ -0,0 +1,22 @@
+import { __ } from 'ramda';
+
+import invokeArgs from './invokeArgs';
+
+/**
+ * Invokes the method at path of object.
+ *
+ * @func invoke
+ * @memberOf RA
+ * @since {@link https://char0n.github.io/ramda-adjunct/2.31.0|v2.31.0}
+ * @category Object
+ * @sig Array -> Object -> *
+ * @param {Array.<string|number>} path The path of the method to invoke
+ * @param {Object} obj The object to query
+ * @return {*}
+ * @example
+ *
+ * RA.invoke(['random'], Math); //=> 0.5113253820009047
+ */
+const invoke = invokeArgs(__, [], __);
+
+export default invoke;
diff --git a/types/index.d.ts b/types/index.d.ts
index 09103c7746..7b0bdff811 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -1466,6 +1466,12 @@ declare namespace RamdaAdjunct {
         invokeArgs(pathToMethod: string[], args: any[]): (obj: object) => any;
         invokeArgs(pathToMethod: string[]): (args: any[], obj: object) => any;
 
+        /**
+         * Invokes the method at path of object.
+         */
+        invoke(pathToMethod: string[], obj: object): any;
+        invoke(pathToMethod: string[]): (obj: object) => any;
+
         /**
          * Converts double-precision 64-bit binary format IEEE 754 to signed 32 bit integer number.
          */


Test patch:
diff --git a/test/invoke.js b/test/invoke.js
new file mode 100644
index 0000000000..8e3ea7f7f7
--- /dev/null
+++ b/test/invoke.js
@@ -0,0 +1,64 @@
+import { assert } from 'chai';
+
+import * as RA from '../src';
+
+describe('invoke', function () {
+  const testObj = {
+    innerObj: {
+      method(a = 1, b = 2, c = 3) {
+        return a + b + c;
+      },
+    },
+    method(a = 2, b = 4, c = 6) {
+      return a + b + c;
+    },
+    methodWithoutArgs() {
+      return 1;
+    },
+    notAMethod: 'Hello',
+  };
+
+  const testFunc = (a = 1, b = 2) => a + b;
+
+  const testContextObj = {
+    prop: 1,
+    method(val = 1) {
+      return this.prop + this.prop + val;
+    },
+    methodWithoutDefaultArg(val) {
+      return this.prop + this.prop + val;
+    },
+  };
+
+  it('should invoke the method at path of object with no arguments', function () {
+    assert.isNaN(RA.invoke(['abs'], Math));
+    assert.strictEqual(RA.invoke(['method'], testObj), 12);
+    assert.strictEqual(RA.invoke(['innerObj', 'method'], testObj), 6);
+    assert.strictEqual(RA.invoke(['methodWithoutArgs'], testObj), 1);
+  });
+
+  it('should be safe', function () {
+    assert.isUndefined(
+      RA.invoke(['path', 'to', 'non-existent', 'method'], Math)
+    );
+    assert.isUndefined(RA.invoke(['unknown'], testObj));
+    assert.isUndefined(RA.invoke(['notAMethod'], testObj));
+    assert.isUndefined(RA.invoke([], testObj));
+    assert.isUndefined(RA.invoke(['notAMethod'], 'testObj'));
+    assert.isUndefined(RA.invoke(['innerObj', 'method', 'unknown'], testObj));
+  });
+
+  it('should be bounded to the context', function () {
+    assert.strictEqual(RA.invoke(['method'], testContextObj), 3);
+    assert.isNaN(RA.invoke(['methodWithoutDefaultArg'], testContextObj));
+  });
+
+  it('should be compatible with another invoke libraries methods', function () {
+    assert.isUndefined(RA.invoke([], testFunc));
+  });
+
+  it('should be curried', function () {
+    assert.isNaN(RA.invoke(['abs'])(Math));
+    assert.isNaN(RA.invoke(['abs'], Math));
+  });
+});
diff --git a/types/test/invoke.ts b/types/test/invoke.ts
new file mode 100644
index 0000000000..570bf8e26f
--- /dev/null
+++ b/types/test/invoke.ts
@@ -0,0 +1,7 @@
+import * as RA from 'ramda-adjunct';
+
+RA.invoke(['random'], Math); // $ExpectType any
+RA.invoke(['nonexistentMethod'], Math); // $ExpectType any
+RA.invoke([0, 'a'], Math); // $ExpectError
+RA.invoke([{}], Math); // $ExpectError
+RA.invoke([0], Math); // $ExpectError