rambda 8.2.0 → 8.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,13 +51,17 @@ import {add} from 'rambda/immutable'
51
51
 
52
52
  ### Deno support
53
53
 
54
- While `Ramda` is available for `Deno` users, `Rambda` provides you with included TS definitions:
54
+ Latest version of **Ramba** available for `Deno` users is 3 years old. This is not the case with **Rambda** as most of recent releases are available for `Deno` users.
55
+
56
+ Also, `Rambda` provides you with included TS definitions:
55
57
 
56
58
  ```
57
- import * as R from "https://x.nest.land/rambda@7.1.0/mod.ts";
58
- import * as Ramda from "https://x.nest.land/ramda@0.28.0/mod.ts";
59
+ // Deno extension(https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
60
+ // is installed and initialized
61
+ import * as R from "https://deno.land/x/rambda/mod.ts";
62
+ import * as Ramda from "https://x.nest.land/ramda@0.27.2/mod.ts";
59
63
 
60
- R.add(1)('foo') // => will trigger warning in VSCode
64
+ R.add(1)('foo') // => will trigger warning in VSCode as it should
61
65
  Ramda.add(1)('foo') // => will not trigger warning in VSCode
62
66
  ```
63
67
 
@@ -86,9 +90,7 @@ R.pick('a,b', {a: 1 , b: 2, c: 3} })
86
90
 
87
91
  ### Support
88
92
 
89
- As the library is smaller than Ramda, issues are much faster resolved.
90
-
91
- Closing the issue is usually accompanied by publishing a new patch version of `Rambda` to NPM.
93
+ One of the main issues with `Ramda` is the slow process of releasing new versions. This is not the case with **Rambda** as releases are made on regular basis.
92
94
 
93
95
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-rambdas-advantages)
94
96
 
@@ -96,18 +98,9 @@ Closing the issue is usually accompanied by publishing a new patch version of `R
96
98
 
97
99
  <details>
98
100
  <summary>
99
- Click to see the full list of 72 Ramda methods not implemented in Rambda
101
+ Click to see the full list of 0 Ramda methods not implemented in Rambda and their status.
100
102
  </summary>
101
103
 
102
- - __
103
- - binary
104
- - call
105
- - collectBy
106
- - comparator
107
- - composeWith
108
- - construct
109
- - constructN
110
- - dissocPath
111
104
  - dropRepeatsBy
112
105
  - empty
113
106
  - eqBy
@@ -159,8 +152,6 @@ Closing the issue is usually accompanied by publishing a new patch version of `R
159
152
  - symmetricDifferenceWith
160
153
  - andThen
161
154
  - toPairsIn
162
- - transduce
163
- - traverse
164
155
  - unary
165
156
  - uncurryN
166
157
  - unfold
@@ -172,6 +163,12 @@ Closing the issue is usually accompanied by publishing a new patch version of `R
172
163
  - thunkify
173
164
  - default
174
165
 
166
+ Most of above methods are in progress to be added to **Rambda**. The following methods are not going to be added:
167
+ - __ - placeholder method allows user to further customize the method call. While, it seems useful initially, the price is too high in terms of complexity for TypeScript definitions. If it is not easy exressable in TypeScript, it is not worth it as **Rambda** is a TypeScript first library.
168
+ - construct - Using classes is not very functional programming oriented.
169
+ - constructN - same as above
170
+ - transduce - currently is out of focus
171
+ - traverse - same as above
175
172
  </details>
176
173
 
177
174
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-missing-ramda-methods)
@@ -189,7 +186,7 @@ https://unpkg.com/rambda@CURRENT_VERSION/dist/rambda.umd.js
189
186
  - with deno
190
187
 
191
188
  ```
192
- import {compose, add} from 'https://raw.githubusercontent.com/selfrefactor/rambda/master/dist/rambda.esm.js'
189
+ import {add} from "https://deno.land/x/rambda/mod.ts";
193
190
  ```
194
191
 
195
192
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-install)
@@ -237,8 +234,8 @@ method | Rambda | Ramda | Lodash
237
234
  --- |--- | --- | ---
238
235
  *add* | 🚀 Fastest | 21.52% slower | 82.15% slower
239
236
  *adjust* | 8.48% slower | 🚀 Fastest | 🔳
240
- *all* | 🚀 Fastest | 1.81% slower | 🔳
241
- *allPass* | 🚀 Fastest | 91.09% slower | 🔳
237
+ *all* | 🚀 Fastest | 7.18% slower | 🔳
238
+ *allPass* | 🚀 Fastest | 88.25% slower | 🔳
242
239
  *allPass* | 🚀 Fastest | 98.56% slower | 🔳
243
240
  *and* | 🚀 Fastest | 89.09% slower | 🔳
244
241
  *any* | 🚀 Fastest | 92.87% slower | 45.82% slower
@@ -247,7 +244,7 @@ method | Rambda | Ramda | Lodash
247
244
  *applySpec* | 🚀 Fastest | 80.43% slower | 🔳
248
245
  *assoc* | 72.32% slower | 60.08% slower | 🚀 Fastest
249
246
  *clone* | 🚀 Fastest | 91.86% slower | 86.48% slower
250
- *compose* | 🚀 Fastest | 32.45% slower | 13.68% slower
247
+ *compose* | 6.07% slower | 16.89% slower | 🚀 Fastest
251
248
  *converge* | 78.63% slower | 🚀 Fastest | 🔳
252
249
  *curry* | 🚀 Fastest | 28.86% slower | 🔳
253
250
  *curryN* | 🚀 Fastest | 41.05% slower | 🔳
@@ -258,10 +255,10 @@ method | Rambda | Ramda | Lodash
258
255
  *filter* | 6.7% slower | 72.03% slower | 🚀 Fastest
259
256
  *find* | 🚀 Fastest | 85.14% slower | 42.65% slower
260
257
  *findIndex* | 🚀 Fastest | 86.48% slower | 72.27% slower
261
- *flatten* | 6.56% slower | 86.64% slower | 🚀 Fastest
258
+ *flatten* | 🚀 Fastest | 85.68% slower | 3.57% slower
262
259
  *ifElse* | 🚀 Fastest | 58.56% slower | 🔳
263
- *includes* | 🚀 Fastest | 84.63% slower | 🔳
264
- *indexOf* | 🚀 Fastest | 76.63% slower | 🔳
260
+ *includes* | 🚀 Fastest | 81.64% slower | 🔳
261
+ *indexOf* | 🚀 Fastest | 80.17% slower | 🔳
265
262
  *indexOf* | 🚀 Fastest | 82.2% slower | 🔳
266
263
  *init* | 🚀 Fastest | 92.24% slower | 13.3% slower
267
264
  *is* | 🚀 Fastest | 57.69% slower | 🔳
@@ -277,7 +274,7 @@ method | Rambda | Ramda | Lodash
277
274
  *over* | 🚀 Fastest | 56.23% slower | 🔳
278
275
  *path* | 37.81% slower | 77.81% slower | 🚀 Fastest
279
276
  *pick* | 🚀 Fastest | 19.07% slower | 80.2% slower
280
- *pipe* | 0.87% slower | 🚀 Fastest | 🔳
277
+ *pipe* | 🚀 Fastest | 0.11% slower | 🔳
281
278
  *prop* | 🚀 Fastest | 87.95% slower | 🔳
282
279
  *propEq* | 🚀 Fastest | 91.92% slower | 🔳
283
280
  *range* | 🚀 Fastest | 61.8% slower | 57.44% slower
@@ -293,8 +290,9 @@ method | Rambda | Ramda | Lodash
293
290
  *takeLast* | 🚀 Fastest | 93.39% slower | 19.22% slower
294
291
  *test* | 🚀 Fastest | 82.34% slower | 🔳
295
292
  *type* | 🚀 Fastest | 48.6% slower | 🔳
296
- *uniq* | 🚀 Fastest | 90.24% slower | 🔳
297
- *uniqWith* | 18.09% slower | 🚀 Fastest | 🔳
293
+ *uniq* | 🚀 Fastest | 84.9% slower | 🔳
294
+ *uniqBy* | 51.93% slower | 🚀 Fastest | 🔳
295
+ *uniqWith* | 8.29% slower | 🚀 Fastest | 🔳
298
296
  *uniqWith* | 14.23% slower | 🚀 Fastest | 🔳
299
297
  *update* | 🚀 Fastest | 52.35% slower | 🔳
300
298
  *view* | 🚀 Fastest | 76.15% slower | 🔳
@@ -791,7 +789,7 @@ describe('R.any', () => {
791
789
 
792
790
  ```typescript
793
791
 
794
- anyPass<T>(predicates: ((x: T) => boolean)[]): (input: T) => boolean
792
+ anyPass<T, U extends T[]>(predicates: { [K in keyof U]: (x: T) => x is U[K]
795
793
  ```
796
794
 
797
795
  It accepts list of `predicates` and returns a function. This function with its `input` will return `true`, if any of `predicates` returns `true` for this `input`.
@@ -803,6 +801,7 @@ It accepts list of `predicates` and returns a function. This function with its `
803
801
  <summary>All TypeScript definitions</summary>
804
802
 
805
803
  ```typescript
804
+ anyPass<T, U extends T[]>(predicates: { [K in keyof U]: (x: T) => x is U[K]; }): (input: T) => input is U[number];
806
805
  anyPass<T>(predicates: ((x: T) => boolean)[]): (input: T) => boolean;
807
806
  anyPass<T>(predicates: ((...inputs: T[]) => boolean)[]): (...inputs: T[]) => boolean;
808
807
  ```
@@ -930,6 +929,21 @@ describe('anyPass', () => {
930
929
  const filtered2 = xs.filter(pred)
931
930
  filtered2 // $ExpectType number[]
932
931
  })
932
+ it('functions as a type guard', () => {
933
+ const isString = (x: unknown): x is string => typeof x === 'string';
934
+ const isNumber = (x: unknown): x is number => typeof x === 'number';
935
+ const isBoolean = (x: unknown): x is boolean => typeof x === 'boolean';
936
+
937
+ const isStringNumberOrBoolean = anyPass([isString, isNumber, isBoolean]);
938
+
939
+ isStringNumberOrBoolean // $ExpectType (input: unknown) => input is string | number | boolean
940
+
941
+ const aValue: unknown = 1;
942
+
943
+ if (isStringNumberOrBoolean(aValue)) {
944
+ aValue // $ExpectType string | number | boolean
945
+ }
946
+ })
933
947
  })
934
948
  ```
935
949
 
@@ -1075,10 +1089,10 @@ test('happy', () => {
1075
1089
 
1076
1090
  ```typescript
1077
1091
 
1078
- append<T>(x: T, list: T[]): T[]
1092
+ append<T>(xToAppend: T, iterable: T[]): T[]
1079
1093
  ```
1080
1094
 
1081
- It adds element `x` at the end of `list`.
1095
+ It adds element `x` at the end of `iterable`.
1082
1096
 
1083
1097
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20x%20%3D%20'foo'%0A%0Aconst%20result%20%3D%20R.append(x%2C%20%5B'bar'%2C%20'baz'%5D)%0A%2F%2F%20%3D%3E%20%5B'bar'%2C%20'baz'%2C%20'foo'%5D">Try this <strong>R.append</strong> example in Rambda REPL</a>
1084
1098
 
@@ -1087,8 +1101,10 @@ It adds element `x` at the end of `list`.
1087
1101
  <summary>All TypeScript definitions</summary>
1088
1102
 
1089
1103
  ```typescript
1090
- append<T>(x: T, list: T[]): T[];
1091
- append<T>(x: T): <T>(list: T[]) => T[];
1104
+ append<T>(xToAppend: T, iterable: T[]): T[];
1105
+ append<T, U>(xToAppend: T, iterable: IsFirstSubtypeOfSecond<T, U>[]) : U[];
1106
+ append<T>(xToAppend: T): <U>(iterable: IsFirstSubtypeOfSecond<T, U>[]) => U[];
1107
+ append<T>(xToAppend: T): (iterable: T[]) => T[];
1092
1108
  ```
1093
1109
 
1094
1110
  </details>
@@ -1119,7 +1135,8 @@ export function append(x, input){
1119
1135
  <summary><strong>Tests</strong></summary>
1120
1136
 
1121
1137
  ```javascript
1122
- import { append } from './append.js'
1138
+ // import { append } from './append.js'
1139
+ import { append } from 'ramda'
1123
1140
 
1124
1141
  test('happy', () => {
1125
1142
  expect(append('tests', [ 'write', 'more' ])).toEqual([
@@ -1145,20 +1162,62 @@ test('with strings', () => {
1145
1162
  <summary><strong>TypeScript</strong> test</summary>
1146
1163
 
1147
1164
  ```typescript
1148
- import {append} from 'rambda'
1165
+ import {append, prepend} from 'rambda'
1149
1166
 
1150
- const list = [1, 2, 3]
1167
+ const listOfNumbers = [1, 2, 3]
1168
+ const listOfNumbersAndStrings = [1, 'b', 3]
1151
1169
 
1152
- describe('R.append', () => {
1153
- it('happy', () => {
1154
- const result = append(4, list)
1170
+ describe('R.append/R.prepend', () => {
1171
+ describe("with the same primitive type as the array's elements", () => {
1172
+ it('uncurried', () => {
1173
+ // @ts-expect-error
1174
+ append('d', listOfNumbers)
1175
+ // @ts-expect-error
1176
+ prepend('d', listOfNumbers)
1177
+ append(4, listOfNumbers) // $ExpectType number[]
1178
+ prepend(4, listOfNumbers) // $ExpectType number[]
1179
+ })
1155
1180
 
1156
- result // $ExpectType number[]
1181
+ it('curried', () => {
1182
+ // @ts-expect-error
1183
+ append('d')(listOfNumbers)
1184
+ append(4)(listOfNumbers) // $ExpectType number[]
1185
+ prepend(4)(listOfNumbers) // $ExpectType number[]
1186
+ })
1157
1187
  })
1158
- it('curried', () => {
1159
- const result = append(4)(list)
1160
1188
 
1161
- result // $ExpectType number[]
1189
+ describe("with a subtype of the array's elements", () => {
1190
+ it('uncurried', () => {
1191
+ // @ts-expect-error
1192
+ append(true, listOfNumbersAndStrings)
1193
+ append(4, listOfNumbersAndStrings) // $ExpectType (string | number)[]
1194
+ prepend(4, listOfNumbersAndStrings) // $ExpectType (string | number)[]
1195
+ })
1196
+
1197
+ it('curried', () => {
1198
+ // @ts-expect-error
1199
+ append(true)(listOfNumbersAndStrings)
1200
+ append(4)(listOfNumbersAndStrings) // $ExpectType (string | number)[]
1201
+ prepend(4)(listOfNumbersAndStrings) // $ExpectType (string | number)[]
1202
+ })
1203
+ })
1204
+
1205
+ describe("expanding the type of the array's elements", () => {
1206
+ it('uncurried', () => {
1207
+ // @ts-expect-error
1208
+ append('d', listOfNumbers)
1209
+ append<string | number>('d', listOfNumbers) // $ExpectType (string | number)[]
1210
+ prepend<string | number>('d', listOfNumbers) // $ExpectType (string | number)[]
1211
+ })
1212
+
1213
+ it('curried', () => {
1214
+ // @ts-expect-error
1215
+ append('d')(listOfNumbers)
1216
+ const appendD = append('d')
1217
+ appendD<string | number>(listOfNumbers) // $ExpectType (string | number)[]
1218
+ const prependD = prepend('d')
1219
+ prependD<string | number>(listOfNumbers) // $ExpectType (string | number)[]
1220
+ })
1162
1221
  })
1163
1222
  })
1164
1223
  ```
@@ -1750,21 +1809,17 @@ assocPath<Output>(path: Path): (newValue: any) => (obj: object) => Output;
1750
1809
 
1751
1810
  ```javascript
1752
1811
  import { cloneList } from './_internals/cloneList.js'
1812
+ import { createPath } from './_internals/createPath.js'
1753
1813
  import { isArray } from './_internals/isArray.js'
1754
- import { isInteger } from './_internals/isInteger.js'
1755
- import { assoc } from './assoc.js'
1814
+ import { isIndexInteger } from './_internals/isInteger.js'
1815
+ import { assocFn } from './assoc.js'
1756
1816
  import { curry } from './curry.js'
1757
1817
 
1758
- function assocPathFn(
1818
+ export function assocPathFn(
1759
1819
  path, newValue, input
1760
1820
  ){
1761
- const pathArrValue =
1762
- typeof path === 'string' ?
1763
- path.split('.').map(x => isInteger(Number(x)) ? Number(x) : x) :
1764
- path
1765
- if (pathArrValue.length === 0){
1766
- return newValue
1767
- }
1821
+ const pathArrValue = createPath(path)
1822
+ if (pathArrValue.length === 0) return newValue
1768
1823
 
1769
1824
  const index = pathArrValue[ 0 ]
1770
1825
  if (pathArrValue.length > 1){
@@ -1774,7 +1829,7 @@ function assocPathFn(
1774
1829
  !input.hasOwnProperty(index)
1775
1830
 
1776
1831
  const nextInput = condition ?
1777
- isInteger(pathArrValue[ 1 ]) ?
1832
+ isIndexInteger(pathArrValue[ 1 ]) ?
1778
1833
  [] :
1779
1834
  {} :
1780
1835
  input[ index ]
@@ -1786,14 +1841,14 @@ function assocPathFn(
1786
1841
  )
1787
1842
  }
1788
1843
 
1789
- if (isInteger(index) && isArray(input)){
1844
+ if (isIndexInteger(index) && isArray(input)){
1790
1845
  const arr = cloneList(input)
1791
1846
  arr[ index ] = newValue
1792
1847
 
1793
1848
  return arr
1794
1849
  }
1795
1850
 
1796
- return assoc(
1851
+ return assocFn(
1797
1852
  index, newValue, input
1798
1853
  )
1799
1854
  }
@@ -1808,21 +1863,45 @@ export const assocPath = curry(assocPathFn)
1808
1863
  <summary><strong>Tests</strong></summary>
1809
1864
 
1810
1865
  ```javascript
1811
- import { assocPath } from './assocPath.js'
1866
+ import { assocPathFn } from './assocPath.js'
1867
+
1868
+ test.only('happy', () => {
1869
+ const path = 'a.c.1'
1870
+ const input = {
1871
+ a : {
1872
+ b : 1,
1873
+ c : [ 1, 2 ],
1874
+ },
1875
+ }
1876
+ assocPathFn(
1877
+ path, 3, input
1878
+ )
1879
+ expect(input).toEqual({
1880
+ a : {
1881
+ b : 1,
1882
+ c : [ 1, 2 ],
1883
+ },
1884
+ })
1885
+ })
1812
1886
 
1813
1887
  test('string can be used as path input', () => {
1814
1888
  const testObj = {
1815
1889
  a : [ { b : 1 }, { b : 2 } ],
1816
1890
  d : 3,
1817
1891
  }
1818
- const result = assocPath(
1892
+ const result1 = assocPathFn(
1893
+ [ 'a', 0, 'b' ], 10, testObj
1894
+ )
1895
+ const result2 = assocPathFn(
1819
1896
  'a.0.b', 10, testObj
1820
1897
  )
1898
+
1821
1899
  const expected = {
1822
1900
  a : [ { b : 10 }, { b : 2 } ],
1823
1901
  d : 3,
1824
1902
  }
1825
- expect(result).toEqual(expected)
1903
+ expect(result1).toEqual(expected)
1904
+ expect(result2).toEqual(expected)
1826
1905
  })
1827
1906
 
1828
1907
  test('difference with ramda - doesn\'t overwrite primitive values with keys in the path', () => {
@@ -2030,6 +2109,10 @@ describe('R.assocPath - curried', () => {
2030
2109
 
2031
2110
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#assocPath)
2032
2111
 
2112
+ ### binary
2113
+
2114
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#binary)
2115
+
2033
2116
  ### bind
2034
2117
 
2035
2118
  ```typescript
@@ -2338,6 +2421,10 @@ describe('R.both', () => {
2338
2421
 
2339
2422
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#both)
2340
2423
 
2424
+ ### call
2425
+
2426
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#call)
2427
+
2341
2428
  ### chain
2342
2429
 
2343
2430
  ```typescript
@@ -2493,6 +2580,14 @@ It creates a deep copy of the `input`, which may contain (nested) Arrays and Obj
2493
2580
 
2494
2581
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#clone)
2495
2582
 
2583
+ ### collectBy
2584
+
2585
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#collectBy)
2586
+
2587
+ ### comparator
2588
+
2589
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#comparator)
2590
+
2496
2591
  ### complement
2497
2592
 
2498
2593
  It returns `inverted` version of `origin` function that accept `input` as argument.
@@ -2511,6 +2606,10 @@ It performs right-to-left function composition.
2511
2606
 
2512
2607
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#compose)
2513
2608
 
2609
+ ### composeWith
2610
+
2611
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#composeWith)
2612
+
2514
2613
  ### concat
2515
2614
 
2516
2615
  It returns a new string or array, which is the result of merging `x` and `y`.
@@ -2972,6 +3071,10 @@ It returns a new object that does not contain property `prop`.
2972
3071
 
2973
3072
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissoc)
2974
3073
 
3074
+ ### dissocPath
3075
+
3076
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissocPath)
3077
+
2975
3078
  ### divide
2976
3079
 
2977
3080
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20R.divide(71%2C%20100)%20%2F%2F%20%3D%3E%200.71">Try this <strong>R.divide</strong> example in Rambda REPL</a>
@@ -3700,43 +3803,39 @@ import { isArray } from './_internals/isArray.js'
3700
3803
  import { type } from './type.js'
3701
3804
 
3702
3805
  export function _lastIndexOf(valueToFind, list){
3703
- if (!isArray(list)){
3806
+ if (!isArray(list))
3704
3807
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3705
- }
3808
+
3706
3809
  const typeOfValue = type(valueToFind)
3707
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3810
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3708
3811
  return list.lastIndexOf(valueToFind)
3709
3812
 
3710
3813
  const { length } = list
3711
3814
  let index = length
3712
3815
  let foundIndex = -1
3713
3816
 
3714
- while (--index > -1 && foundIndex === -1){
3715
- if (equals(list[ index ], valueToFind)){
3817
+ while (--index > -1 && foundIndex === -1)
3818
+ if (equals(list[ index ], valueToFind))
3716
3819
  foundIndex = index
3717
- }
3718
- }
3719
3820
 
3720
3821
  return foundIndex
3721
3822
  }
3722
3823
 
3723
3824
  export function _indexOf(valueToFind, list){
3724
- if (!isArray(list)){
3825
+ if (!isArray(list))
3725
3826
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3726
- }
3827
+
3727
3828
  const typeOfValue = type(valueToFind)
3728
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3829
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3729
3830
  return list.indexOf(valueToFind)
3730
3831
 
3731
3832
  let index = -1
3732
3833
  let foundIndex = -1
3733
3834
  const { length } = list
3734
3835
 
3735
- while (++index < length && foundIndex === -1){
3736
- if (equals(list[ index ], valueToFind)){
3836
+ while (++index < length && foundIndex === -1)
3837
+ if (equals(list[ index ], valueToFind))
3737
3838
  foundIndex = index
3738
- }
3739
- }
3740
3839
 
3741
3840
  return foundIndex
3742
3841
  }
@@ -3744,17 +3843,16 @@ export function _indexOf(valueToFind, list){
3744
3843
  function _arrayFromIterator(iter){
3745
3844
  const list = []
3746
3845
  let next
3747
- while (!(next = iter.next()).done){
3846
+ while (!(next = iter.next()).done)
3748
3847
  list.push(next.value)
3749
- }
3750
3848
 
3751
3849
  return list
3752
3850
  }
3753
3851
 
3754
- function _equalsSets(a, b){
3755
- if (a.size !== b.size){
3852
+ function _compareSets(a, b){
3853
+ if (a.size !== b.size)
3756
3854
  return false
3757
- }
3855
+
3758
3856
  const aList = _arrayFromIterator(a.values())
3759
3857
  const bList = _arrayFromIterator(b.values())
3760
3858
 
@@ -3763,11 +3861,11 @@ function _equalsSets(a, b){
3763
3861
  return filtered.length === 0
3764
3862
  }
3765
3863
 
3766
- function parseError(maybeError){
3767
- const typeofError = maybeError.__proto__.toString()
3768
- if (![ 'Error', 'TypeError' ].includes(typeofError)) return []
3864
+ function compareErrors(a, b){
3865
+ if (a.message !== b.message) return false
3866
+ if (a.toString !== b.toString) return false
3769
3867
 
3770
- return [ typeofError, maybeError.message ]
3868
+ return a.toString() === b.toString()
3771
3869
  }
3772
3870
 
3773
3871
  function parseDate(maybeDate){
@@ -3788,40 +3886,36 @@ export function equals(a, b){
3788
3886
  const aType = type(a)
3789
3887
 
3790
3888
  if (aType !== type(b)) return false
3791
- if (aType === 'Function'){
3889
+ if (aType === 'Function')
3792
3890
  return a.name === undefined ? false : a.name === b.name
3793
- }
3794
3891
 
3795
- if ([ 'NaN', 'Undefined', 'Null' ].includes(aType)) return true
3892
+ if ([ 'NaN', 'Null', 'Undefined' ].includes(aType)) return true
3796
3893
 
3797
- if (aType === 'Number'){
3894
+ if ([ 'BigInt', 'Number' ].includes(aType)){
3798
3895
  if (Object.is(-0, a) !== Object.is(-0, b)) return false
3799
3896
 
3800
3897
  return a.toString() === b.toString()
3801
3898
  }
3802
3899
 
3803
- if ([ 'String', 'Boolean' ].includes(aType)){
3900
+ if ([ 'Boolean', 'String' ].includes(aType))
3804
3901
  return a.toString() === b.toString()
3805
- }
3806
3902
 
3807
3903
  if (aType === 'Array'){
3808
3904
  const aClone = Array.from(a)
3809
3905
  const bClone = Array.from(b)
3810
3906
 
3811
- if (aClone.toString() !== bClone.toString()){
3907
+ if (aClone.toString() !== bClone.toString())
3812
3908
  return false
3813
- }
3814
3909
 
3815
3910
  let loopArrayFlag = true
3816
3911
  aClone.forEach((aCloneInstance, aCloneIndex) => {
3817
- if (loopArrayFlag){
3912
+ if (loopArrayFlag)
3818
3913
  if (
3819
3914
  aCloneInstance !== bClone[ aCloneIndex ] &&
3820
3915
  !equals(aCloneInstance, bClone[ aCloneIndex ])
3821
- ){
3916
+ )
3822
3917
  loopArrayFlag = false
3823
- }
3824
- }
3918
+
3825
3919
  })
3826
3920
 
3827
3921
  return loopArrayFlag
@@ -3830,34 +3924,31 @@ export function equals(a, b){
3830
3924
  const aRegex = parseRegex(a)
3831
3925
  const bRegex = parseRegex(b)
3832
3926
 
3833
- if (aRegex[ 0 ]){
3927
+ if (aRegex[ 0 ])
3834
3928
  return bRegex[ 0 ] ? aRegex[ 1 ] === bRegex[ 1 ] : false
3835
- } else if (bRegex[ 0 ]) return false
3929
+ else if (bRegex[ 0 ]) return false
3836
3930
 
3837
3931
  const aDate = parseDate(a)
3838
3932
  const bDate = parseDate(b)
3839
3933
 
3840
- if (aDate[ 0 ]){
3934
+ if (aDate[ 0 ])
3841
3935
  return bDate[ 0 ] ? aDate[ 1 ] === bDate[ 1 ] : false
3842
- } else if (bDate[ 0 ]) return false
3936
+ else if (bDate[ 0 ]) return false
3843
3937
 
3844
- const aError = parseError(a)
3845
- const bError = parseError(b)
3938
+ if (a instanceof Error){
3939
+ if (!(b instanceof Error)) return false
3846
3940
 
3847
- if (aError[ 0 ]){
3848
- return bError[ 0 ] ?
3849
- aError[ 0 ] === bError[ 0 ] && aError[ 1 ] === bError[ 1 ] :
3850
- false
3851
- }
3852
- if (aType === 'Set'){
3853
- return _equalsSets(a, b)
3941
+ return compareErrors(a, b)
3854
3942
  }
3943
+
3944
+ if (aType === 'Set')
3945
+ return _compareSets(a, b)
3946
+
3855
3947
  if (aType === 'Object'){
3856
3948
  const aKeys = Object.keys(a)
3857
3949
 
3858
- if (aKeys.length !== Object.keys(b).length){
3950
+ if (aKeys.length !== Object.keys(b).length)
3859
3951
  return false
3860
- }
3861
3952
 
3862
3953
  let loopObjectFlag = true
3863
3954
  aKeys.forEach(aKeyInstance => {
@@ -3865,9 +3956,9 @@ export function equals(a, b){
3865
3956
  const aValue = a[ aKeyInstance ]
3866
3957
  const bValue = b[ aKeyInstance ]
3867
3958
 
3868
- if (aValue !== bValue && !equals(aValue, bValue)){
3959
+ if (aValue !== bValue && !equals(aValue, bValue))
3869
3960
  loopObjectFlag = false
3870
- }
3961
+
3871
3962
  }
3872
3963
  })
3873
3964
 
@@ -3954,6 +4045,7 @@ test('new Error', () => {
3954
4045
  expect(equals(new Error('XXX'), new Error('YYY'))).toBeFalse()
3955
4046
  expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3956
4047
  expect(equals(new Error('XXX'), new TypeError('YYY'))).toBeFalse()
4048
+ expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3957
4049
  })
3958
4050
 
3959
4051
  test('with dates', () => {
@@ -3982,8 +4074,8 @@ test('ramda spec', () => {
3982
4074
  b : 3,
3983
4075
  },
3984
4076
  {
3985
- b : 3,
3986
4077
  a : 2,
4078
+ b : 3,
3987
4079
  })).toBeTrue()
3988
4080
 
3989
4081
  expect(equals({
@@ -4079,8 +4171,8 @@ test('various examples', () => {
4079
4171
  b : 2,
4080
4172
  },
4081
4173
  {
4082
- b : 2,
4083
4174
  a : 1,
4175
+ b : 2,
4084
4176
  })).toBeTrue()
4085
4177
 
4086
4178
  expect(equals({
@@ -4106,8 +4198,8 @@ test('various examples', () => {
4106
4198
  b : 2,
4107
4199
  },
4108
4200
  {
4109
- b : 2,
4110
4201
  a : 1,
4202
+ b : 2,
4111
4203
  c : 3,
4112
4204
  })).toBeFalse()
4113
4205
 
@@ -4119,8 +4211,8 @@ test('various examples', () => {
4119
4211
  },
4120
4212
  {
4121
4213
  x : {
4122
- b : 2,
4123
4214
  a : 1,
4215
+ b : 2,
4124
4216
  c : 3,
4125
4217
  },
4126
4218
  })).toBeFalse()
@@ -4130,8 +4222,8 @@ test('various examples', () => {
4130
4222
  b : 2,
4131
4223
  },
4132
4224
  {
4133
- b : 3,
4134
4225
  a : 1,
4226
+ b : 3,
4135
4227
  })).toBeFalse()
4136
4228
 
4137
4229
  expect(equals({ a : { b : { c : 1 } } }, { a : { b : { c : 1 } } })).toBeTrue()
@@ -4180,26 +4272,32 @@ test('with negative zero', () => {
4180
4272
  expect(equals(-0, 1)).toBeFalse()
4181
4273
  })
4182
4274
 
4183
- const possibleInputs = variousTypes
4275
+ test('with big int', () => {
4276
+ const a = BigInt(9007199254740991)
4277
+ const b = BigInt(9007199254740991)
4278
+ const c = BigInt(7007199254740991)
4279
+ expect(equals(a, b)).toBeTrue()
4280
+ expect(equals(a, c)).toBeFalse()
4281
+ })
4184
4282
 
4185
4283
  describe('brute force', () => {
4186
4284
  compareCombinations({
4187
- fn : equals,
4188
- fnRamda : equalsRamda,
4189
- firstInput : possibleInputs,
4190
- secondInput : possibleInputs,
4191
- callback : errorsCounters => {
4285
+ callback : errorsCounters => {
4192
4286
  expect(errorsCounters).toMatchInlineSnapshot(`
4193
- {
4194
- "ERRORS_MESSAGE_MISMATCH": 0,
4195
- "ERRORS_TYPE_MISMATCH": 0,
4196
- "RESULTS_MISMATCH": 5,
4197
- "SHOULD_NOT_THROW": 4,
4198
- "SHOULD_THROW": 0,
4199
- "TOTAL_TESTS": 289,
4200
- }
4201
- `)
4287
+ {
4288
+ "ERRORS_MESSAGE_MISMATCH": 0,
4289
+ "ERRORS_TYPE_MISMATCH": 0,
4290
+ "RESULTS_MISMATCH": 8,
4291
+ "SHOULD_NOT_THROW": 0,
4292
+ "SHOULD_THROW": 0,
4293
+ "TOTAL_TESTS": 289,
4294
+ }
4295
+ `)
4202
4296
  },
4297
+ firstInput : variousTypes,
4298
+ fn : equals,
4299
+ fnRamda : equalsRamda,
4300
+ secondInput : variousTypes,
4203
4301
  })
4204
4302
  })
4205
4303
  ```
@@ -5701,7 +5799,7 @@ describe('R.hasPath', () => {
5701
5799
 
5702
5800
  ```typescript
5703
5801
 
5704
- head(input: string): string
5802
+ head(str: string): string
5705
5803
  ```
5706
5804
 
5707
5805
  It returns the first element of list or string `input`.
@@ -5713,8 +5811,10 @@ It returns the first element of list or string `input`.
5713
5811
  <summary>All TypeScript definitions</summary>
5714
5812
 
5715
5813
  ```typescript
5716
- head(input: string): string;
5717
- head(emptyList: []): undefined;
5814
+ head(str: string): string;
5815
+ head(str: ''): undefined;
5816
+ head<T>(list: never[]): undefined;
5817
+ head<T extends unknown[]>(array: T): FirstArrayElement<T>
5718
5818
  head<T extends readonly unknown[]>(array: T): FirstArrayElement<T>
5719
5819
  ```
5720
5820
 
@@ -5756,34 +5856,46 @@ test('head', () => {
5756
5856
  <summary><strong>TypeScript</strong> test</summary>
5757
5857
 
5758
5858
  ```typescript
5759
- import {mixedList, mixedListConst} from '_internals/typescriptTestUtils'
5760
- import {head} from 'rambda'
5859
+ import {
5860
+ emptyList,
5861
+ emptyString,
5862
+ mixedList,
5863
+ mixedListConst,
5864
+ numberList,
5865
+ numberListConst,
5866
+ string,
5867
+ } from '_internals/typescriptTestUtils'
5868
+ import {head, last} from 'rambda'
5761
5869
 
5762
5870
  describe('R.head', () => {
5763
5871
  it('string', () => {
5764
- const result = head('foo')
5765
- result // $ExpectType string
5872
+ head(string) // $ExpectType string
5873
+ last(string) // $ExpectType string
5766
5874
  })
5767
- it('array', () => {
5768
- const result = head([1, 2, 3])
5769
- result // $ExpectType number
5770
- })
5771
- it('mixed', () => {
5772
- const result = head(mixedList)
5773
- result // $ExpectType string | number
5875
+ it('empty string', () => {
5876
+ head(emptyString) // $ExpectType undefined
5877
+ last(emptyString) // $ExpectType undefined
5774
5878
  })
5775
- it('mixed const', () => {
5776
- const result = head(mixedListConst)
5777
- result // $ExpectType 1
5879
+ it('array', () => {
5880
+ head(numberList) // $ExpectType number
5881
+ head(numberListConst) // $ExpectType 1
5882
+
5883
+ last(numberList) // $ExpectType number
5884
+ last(numberListConst) // $ExpectType 3
5778
5885
  })
5779
- it('empty array - case 1', () => {
5780
- const result = head([])
5781
- result // $ExpectType undefined
5886
+ it('empty array', () => {
5887
+ const list = [] as const
5888
+ head(emptyList) // $ExpectType undefined
5889
+ head(list) // $ExpectType never
5890
+ last(emptyList) // $ExpectType undefined
5891
+ last(list) // $ExpectType never
5782
5892
  })
5783
- it('empty array - case 2', () => {
5784
- const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
5785
- const result = head(list)
5786
- result // $ExpectType string
5893
+
5894
+ it('mixed', () => {
5895
+ head(mixedList) // $ExpectType string | number
5896
+ head(mixedListConst) // $ExpectType 1
5897
+ last(mixedList) // $ExpectType string | number
5898
+ last(mixedListConst) // $ExpectType "bar"
5787
5899
  })
5788
5900
  })
5789
5901
  ```
@@ -6678,7 +6790,7 @@ describe('R.juxt', () => {
6678
6790
 
6679
6791
  ```typescript
6680
6792
 
6681
- keys<T extends object>(x: T): (keyof T)[]
6793
+ keys<T extends object>(x: T): (keyof T & string)[]
6682
6794
  ```
6683
6795
 
6684
6796
  It applies `Object.keys` over `x` and returns its keys.
@@ -6690,7 +6802,7 @@ It applies `Object.keys` over `x` and returns its keys.
6690
6802
  <summary>All TypeScript definitions</summary>
6691
6803
 
6692
6804
  ```typescript
6693
- keys<T extends object>(x: T): (keyof T)[];
6805
+ keys<T extends object>(x: T): (keyof T & string)[];
6694
6806
  keys<T>(x: T): string[];
6695
6807
  ```
6696
6808
 
@@ -6722,32 +6834,13 @@ test('happy', () => {
6722
6834
 
6723
6835
  </details>
6724
6836
 
6725
- <details>
6726
-
6727
- <summary><strong>TypeScript</strong> test</summary>
6728
-
6729
- ```typescript
6730
- import {keys} from 'rambda'
6731
-
6732
- const obj = {a: 1, b: 2}
6733
-
6734
- describe('R.keys', () => {
6735
- it('happy', () => {
6736
- const result = keys(obj)
6737
- result // $ExpectType ("b" | "a")[]
6738
- })
6739
- })
6740
- ```
6741
-
6742
- </details>
6743
-
6744
6837
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#keys)
6745
6838
 
6746
6839
  ### last
6747
6840
 
6748
6841
  ```typescript
6749
6842
 
6750
- last(input: string): string
6843
+ last(str: ''): undefined
6751
6844
  ```
6752
6845
 
6753
6846
  It returns the last element of `input`, as the `input` can be either a string or an array.
@@ -6759,8 +6852,10 @@ It returns the last element of `input`, as the `input` can be either a string or
6759
6852
  <summary>All TypeScript definitions</summary>
6760
6853
 
6761
6854
  ```typescript
6762
- last(input: string): string;
6763
- last(emptyList: []): undefined;
6855
+ last(str: ''): undefined;
6856
+ last(str: string): string;
6857
+ last(list: never[]): undefined;
6858
+ last<T extends unknown[]>(array: T): LastArrayElement<T>
6764
6859
  last<T extends readonly unknown[]>(array: T): LastArrayElement<T>
6765
6860
  ```
6766
6861
 
@@ -6802,45 +6897,6 @@ test('with string', () => {
6802
6897
 
6803
6898
  </details>
6804
6899
 
6805
- <details>
6806
-
6807
- <summary><strong>TypeScript</strong> test</summary>
6808
-
6809
- ```typescript
6810
- import {mixedList, mixedListConst} from '_internals/typescriptTestUtils'
6811
- import {last} from 'rambda'
6812
-
6813
- describe('R.last', () => {
6814
- it('string', () => {
6815
- const result = last('foo')
6816
- result // $ExpectType string
6817
- })
6818
- it('array', () => {
6819
- const result = last([1, 2, 3])
6820
- result // $ExpectType number
6821
- })
6822
- it('mixed', () => {
6823
- const result = last(mixedList)
6824
- result // $ExpectType string | number
6825
- })
6826
- it('mixed const', () => {
6827
- const result = last(mixedListConst)
6828
- result // $ExpectType "bar"
6829
- })
6830
- it('empty array - case 1', () => {
6831
- const result = last([])
6832
- result // $ExpectType undefined
6833
- })
6834
- it('empty array - case 2', () => {
6835
- const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
6836
- const result = last(list)
6837
- result // $ExpectType string
6838
- })
6839
- })
6840
- ```
6841
-
6842
- </details>
6843
-
6844
6900
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#last)
6845
6901
 
6846
6902
  ### lastIndexOf
@@ -9619,22 +9675,20 @@ omit<T>(propsToOmit: string): (obj: object) => T;
9619
9675
 
9620
9676
  ```javascript
9621
9677
  import { createPath } from './_internals/createPath.js'
9678
+ import { includes } from './_internals/includes.js'
9622
9679
 
9623
9680
  export function omit(propsToOmit, obj){
9624
9681
  if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)
9625
9682
 
9626
- if (obj === null || obj === undefined){
9683
+ if (obj === null || obj === undefined)
9627
9684
  return undefined
9628
- }
9629
9685
 
9630
9686
  const propsToOmitValue = createPath(propsToOmit, ',')
9631
9687
  const willReturn = {}
9632
9688
 
9633
- for (const key in obj){
9634
- if (!propsToOmitValue.includes(key)){
9689
+ for (const key in obj)
9690
+ if (!includes(key, propsToOmitValue))
9635
9691
  willReturn[ key ] = obj[ key ]
9636
- }
9637
- }
9638
9692
 
9639
9693
  return willReturn
9640
9694
  }
@@ -9663,18 +9717,17 @@ test('with string as condition', () => {
9663
9717
  expect(resultCurry).toEqual(expectedResult)
9664
9718
  })
9665
9719
 
9666
- test('with null', () => {
9667
- expect(omit('a,b', null)).toBeUndefined()
9720
+ test.only('with number as property to omit', () => {
9721
+ const obj = {
9722
+ 1 : 1,
9723
+ b : 2,
9724
+ }
9725
+ const result = omit([ 1 ], obj)
9726
+ expect(result).toEqual({ b : 2 })
9668
9727
  })
9669
9728
 
9670
- test('doesn\'t work with number as property', () => {
9671
- expect(omit([ 42 ], {
9672
- a : 1,
9673
- 42 : 2,
9674
- })).toEqual({
9675
- 42 : 2,
9676
- a : 1,
9677
- })
9729
+ test('with null', () => {
9730
+ expect(omit('a,b', null)).toBeUndefined()
9678
9731
  })
9679
9732
 
9680
9733
  test('happy', () => {
@@ -10020,7 +10073,18 @@ test('index lens', () => {
10020
10073
 
10021
10074
  ```typescript
10022
10075
 
10023
- partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T
10076
+ partial<
10077
+ Args extends unknown[],
10078
+ ArgsGiven extends [...Partial<Args>],
10079
+ R
10080
+ >(
10081
+ fn: (...args: Args) => R,
10082
+ ...args: ArgsGiven
10083
+ ): Args extends [...{[K in keyof ArgsGiven]: Args[K]}, ...infer ArgsRemaining]
10084
+ ? ArgsRemaining extends []
10085
+ ? R
10086
+ : (...args: ArgsRemaining) => R
10087
+ : never
10024
10088
  ```
10025
10089
 
10026
10090
  It is very similar to `R.curry`, but you can pass initial arguments when you create the curried function.
@@ -10035,13 +10099,31 @@ The name comes from the fact that you partially inject the inputs.
10035
10099
  <summary>All TypeScript definitions</summary>
10036
10100
 
10037
10101
  ```typescript
10038
- partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T;
10039
- partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0, V1]): (x2: V2) => T;
10040
- partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0]): (x1: V1, x2: V2) => T;
10041
- partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1, V2]): (x2: V3) => T;
10042
- partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1]): (x2: V2, x3: V3) => T;
10043
- partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0]): (x1: V1, x2: V2, x3: V3) => T;
10044
- partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
10102
+ partial<
10103
+ Args extends unknown[],
10104
+ ArgsGiven extends [...Partial<Args>],
10105
+ R
10106
+ >(
10107
+ fn: (...args: Args) => R,
10108
+ ...args: ArgsGiven
10109
+ ): Args extends [...{[K in keyof ArgsGiven]: Args[K]}, ...infer ArgsRemaining]
10110
+ ? ArgsRemaining extends []
10111
+ ? R
10112
+ : (...args: ArgsRemaining) => R
10113
+ : never;
10114
+
10115
+ partial<
10116
+ Args extends readonly unknown[],
10117
+ ArgsGiven extends [...Partial<Args>],
10118
+ R
10119
+ >(
10120
+ fn: (...args: Args) => R,
10121
+ args: ArgsGiven
10122
+ ): Args extends [...{[K in keyof ArgsGiven]: Args[K]}, ...infer ArgsRemaining]
10123
+ ? ArgsRemaining extends []
10124
+ ? R
10125
+ : (...args: ArgsRemaining) => R
10126
+ : never;
10045
10127
  ```
10046
10128
 
10047
10129
  </details>
@@ -10051,15 +10133,21 @@ partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
10051
10133
  <summary><strong>R.partial</strong> source</summary>
10052
10134
 
10053
10135
  ```javascript
10136
+ import { isArray } from './_internals/isArray.js'
10137
+
10054
10138
  export function partial(fn, ...args){
10055
10139
  const len = fn.length
10056
10140
 
10141
+ // If a single array argument is given, those are the args (a la Ramda).
10142
+ // Otherwise, the variadic arguments are the args.
10143
+ const argList = args.length === 1 && isArray(args[0]) ? args[0] : args
10144
+
10057
10145
  return (...rest) => {
10058
- if (args.length + rest.length >= len){
10059
- return fn(...args, ...rest)
10146
+ if (argList.length + rest.length >= len){
10147
+ return fn(...argList, ...rest)
10060
10148
  }
10061
10149
 
10062
- return partial(fn, ...[ ...args, ...rest ])
10150
+ return partial(fn, ...[ ...argList, ...rest ])
10063
10151
  }
10064
10152
  }
10065
10153
  ```
@@ -10077,7 +10165,7 @@ import { type } from './type.js'
10077
10165
  const greet = (
10078
10166
  salutation, title, firstName, lastName
10079
10167
  ) =>
10080
- salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!'
10168
+ [salutation, title, firstName, lastName]
10081
10169
 
10082
10170
  test('happy', () => {
10083
10171
  const canPassAnyNumberOfArguments = partial(
@@ -10089,8 +10177,8 @@ test('happy', () => {
10089
10177
 
10090
10178
  expect(type(fn)).toBe('Function')
10091
10179
 
10092
- expect(fn('bar')).toBe('Hello, Ms. foo bar!')
10093
- expect(sayHelloRamda('foo', 'bar')).toBe('Hello, Ms. foo bar!')
10180
+ expect(fn('bar')).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10181
+ expect(sayHelloRamda('foo', 'bar')).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10094
10182
  })
10095
10183
 
10096
10184
  test('extra arguments are ignored', () => {
@@ -10103,7 +10191,7 @@ test('extra arguments are ignored', () => {
10103
10191
 
10104
10192
  expect(fn(
10105
10193
  'bar', 1, 2
10106
- )).toBe('Hello, Ms. foo bar!')
10194
+ )).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10107
10195
  })
10108
10196
 
10109
10197
  test('when array is input', () => {
@@ -10131,7 +10219,7 @@ test('ramda spec', () => {
10131
10219
  const sayHello = partial(greet, 'Hello')
10132
10220
  const sayHelloToMs = partial(sayHello, 'Ms.')
10133
10221
 
10134
- expect(sayHelloToMs('Jane', 'Jones')).toBe('Hello, Ms. Jane Jones!')
10222
+ expect(sayHelloToMs('Jane', 'Jones')).toStrictEqual(['Hello', 'Ms.', 'Jane', 'Jones'])
10135
10223
  })
10136
10224
  ```
10137
10225
 
@@ -10146,21 +10234,50 @@ import {partial} from 'rambda'
10146
10234
 
10147
10235
  describe('R.partial', () => {
10148
10236
  it('happy', () => {
10149
- function greet(
10150
- salutation: string,
10151
- title: string,
10152
- firstName: string,
10153
- lastName: string
10237
+ function fn(
10238
+ aString: string,
10239
+ aNumber: number,
10240
+ aBoolean: boolean,
10241
+ aNull: null
10154
10242
  ) {
10155
- return `${salutation}, ${title} ${firstName} ${lastName}!`
10243
+ return { aString, aNumber, aBoolean, aNull }
10156
10244
  }
10157
10245
 
10158
- const sayHello = partial(greet, ['Hello'])
10159
- const sayHelloToMs = partial(sayHello, ['Ms.'])
10160
- const result = sayHelloToMs('Jane', 'Jones')
10161
- result // $ExpectType string
10246
+ // @ts-expect-error
10247
+ partial(fn, 1);
10248
+
10249
+ const fn1 = partial(fn, 'a')
10250
+
10251
+ // @ts-expect-error
10252
+ partial(fn1, 'b');
10253
+
10254
+ const fn2 = partial(fn1, 2)
10255
+ const result = fn2(true, null)
10256
+ result // $ExpectType { aString: string; aNumber: number; aBoolean: boolean; aNull: null; }
10162
10257
  })
10163
- })
10258
+
10259
+ it('ramda', () => {
10260
+ function fn(
10261
+ aString: string,
10262
+ aNumber: number,
10263
+ aBoolean: boolean,
10264
+ aNull: null
10265
+ ) {
10266
+ return { aString, aNumber, aBoolean, aNull }
10267
+ }
10268
+
10269
+ // @ts-expect-error
10270
+ partial(fn, 1);
10271
+
10272
+ const fn1 = partial(fn, ['a'])
10273
+
10274
+ // @ts-expect-error
10275
+ partial(fn1, ['b']);
10276
+
10277
+ const fn2 = partial(fn1, [2])
10278
+ const result = fn2(true, null)
10279
+ result // $ExpectType { aString: string; aNumber: number; aBoolean: boolean; aNull: null; }
10280
+ })})
10164
10281
  ```
10165
10282
 
10166
10283
  </details>
@@ -11303,10 +11420,10 @@ test('works with list as input and number as props - props to pick is a string',
11303
11420
  test('with symbol', () => {
11304
11421
  const symbolProp = Symbol('s')
11305
11422
  expect(pick([ symbolProp ], { [ symbolProp ] : 'a' })).toMatchInlineSnapshot(`
11306
- {
11307
- Symbol(s): "a",
11308
- }
11309
- `)
11423
+ {
11424
+ Symbol(s): "a",
11425
+ }
11426
+ `)
11310
11427
  })
11311
11428
  ```
11312
11429
 
@@ -11659,7 +11776,7 @@ describe('R.pluck', () => {
11659
11776
 
11660
11777
  ```typescript
11661
11778
 
11662
- prepend<T>(x: T, input: T[]): T[]
11779
+ prepend<T>(xToPrepend: T, iterable: T[]): T[]
11663
11780
  ```
11664
11781
 
11665
11782
  It adds element `x` at the beginning of `list`.
@@ -11671,8 +11788,10 @@ It adds element `x` at the beginning of `list`.
11671
11788
  <summary>All TypeScript definitions</summary>
11672
11789
 
11673
11790
  ```typescript
11674
- prepend<T>(x: T, input: T[]): T[];
11675
- prepend<T>(x: T): (input: T[]) => T[];
11791
+ prepend<T>(xToPrepend: T, iterable: T[]): T[];
11792
+ prepend<T, U>(xToPrepend: T, iterable: IsFirstSubtypeOfSecond<T, U>[]) : U[];
11793
+ prepend<T>(xToPrepend: T): <U>(iterable: IsFirstSubtypeOfSecond<T, U>[]) => U[];
11794
+ prepend<T>(xToPrepend: T): (iterable: T[]) => T[];
11676
11795
  ```
11677
11796
 
11678
11797
  </details>
@@ -11720,31 +11839,6 @@ test('with string instead of array', () => {
11720
11839
 
11721
11840
  </details>
11722
11841
 
11723
- <details>
11724
-
11725
- <summary><strong>TypeScript</strong> test</summary>
11726
-
11727
- ```typescript
11728
- import {prepend} from 'rambda'
11729
-
11730
- const list = [1, 2, 3]
11731
-
11732
- describe('R.prepend', () => {
11733
- it('happy', () => {
11734
- const result = prepend(4, list)
11735
-
11736
- result // $ExpectType number[]
11737
- })
11738
- it('curried', () => {
11739
- const result = prepend(4)(list)
11740
-
11741
- result // $ExpectType number[]
11742
- })
11743
- })
11744
- ```
11745
-
11746
- </details>
11747
-
11748
11842
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prepend)
11749
11843
 
11750
11844
  ### product
@@ -11822,7 +11916,7 @@ describe('R.product', () => {
11822
11916
 
11823
11917
  ```typescript
11824
11918
 
11825
- prop<P extends keyof never, T>(propToFind: P, value: T): Prop<T, P>
11919
+ prop<_, P extends keyof never, T>(p: P, value: T): Prop<T, P>
11826
11920
  ```
11827
11921
 
11828
11922
  It returns the value of property `propToFind` in `obj`.
@@ -11836,17 +11930,10 @@ If there is no such property, it returns `undefined`.
11836
11930
  <summary>All TypeScript definitions</summary>
11837
11931
 
11838
11932
  ```typescript
11839
- prop<P extends keyof never, T>(propToFind: P, value: T): Prop<T, P>;
11840
- prop<P extends keyof never>(propToFind: P): {
11841
- <T>(value: Record<P, T>): T;
11842
- <T>(value: T): Prop<T, P>;
11843
- };
11844
- prop<P extends keyof T, T>(propToFind: P): {
11845
- (value: T): Prop<T, P>;
11846
- };
11847
- prop<P extends keyof never, T>(propToFind: P): {
11848
- (value: Record<P, T>): T;
11849
- };
11933
+ prop<_, P extends keyof never, T>(p: P, value: T): Prop<T, P>;
11934
+ prop<V>(p: keyof never, value: unknown): V;
11935
+ prop<_, P extends keyof never>(p: P): <T>(value: T) => Prop<T, P>;
11936
+ prop<V>(p: keyof never): (value: unknown) => V;
11850
11937
  ```
11851
11938
 
11852
11939
  </details>
@@ -12713,6 +12800,96 @@ describe('R.reject with objects', () => {
12713
12800
 
12714
12801
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reject)
12715
12802
 
12803
+ ### removeIndex
12804
+
12805
+ ```typescript
12806
+
12807
+ removeIndex<T>(index: number, list: T[]): T[]
12808
+ ```
12809
+
12810
+ It returns a copy of `list` input with removed `index`.
12811
+
12812
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20list%20%3D%20%5B1%2C%202%2C%203%2C%204%5D%0Aconst%20result%20%3D%20R.removeIndex(1%2C%20list)%0A%2F%2F%20%3D%3E%20%5B1%2C%203%2C%204%5D">Try this <strong>R.removeIndex</strong> example in Rambda REPL</a>
12813
+
12814
+ <details>
12815
+
12816
+ <summary>All TypeScript definitions</summary>
12817
+
12818
+ ```typescript
12819
+ removeIndex<T>(index: number, list: T[]): T[];
12820
+ removeIndex(index: number): <T>(list: T[]) => T[];
12821
+ ```
12822
+
12823
+ </details>
12824
+
12825
+ <details>
12826
+
12827
+ <summary><strong>R.removeIndex</strong> source</summary>
12828
+
12829
+ ```javascript
12830
+ export function removeIndex(index, list){
12831
+ if (arguments.length === 1) return _list => removeIndex(index, _list)
12832
+ if (index <= 0) return list.slice(1)
12833
+ if (index >= list.length - 1) return list.slice(0, list.length - 1)
12834
+
12835
+ return [ ...list.slice(0, index), ...list.slice(index + 1) ]
12836
+ }
12837
+ ```
12838
+
12839
+ </details>
12840
+
12841
+ <details>
12842
+
12843
+ <summary><strong>Tests</strong></summary>
12844
+
12845
+ ```javascript
12846
+ import { removeIndex } from './removeIndex.js'
12847
+
12848
+ const list = [ 1, 2, 3, 4 ]
12849
+
12850
+ test('first or before first index', () => {
12851
+ expect(removeIndex(-2, list)).toEqual([ 2, 3, 4 ])
12852
+ expect(removeIndex(-2)(list)).toEqual([ 2, 3, 4 ])
12853
+ })
12854
+
12855
+ test('last or after last index', () => {
12856
+ expect(removeIndex(4, list)).toEqual([ 1, 2, 3 ])
12857
+ expect(removeIndex(10, list)).toEqual([ 1, 2, 3 ])
12858
+ })
12859
+
12860
+ test('middle index', () => {
12861
+ expect(removeIndex(1, list)).toEqual([ 1, 3, 4 ])
12862
+ expect(removeIndex(2, list)).toEqual([ 1, 2, 4 ])
12863
+ })
12864
+ ```
12865
+
12866
+ </details>
12867
+
12868
+ <details>
12869
+
12870
+ <summary><strong>TypeScript</strong> test</summary>
12871
+
12872
+ ```typescript
12873
+ import {removeIndex} from 'rambda'
12874
+
12875
+ describe('R.removeIndex', () => {
12876
+ it('happy', () => {
12877
+ const result = removeIndex(1, [1, 2, 3])
12878
+
12879
+ result // $ExpectType number[]
12880
+ })
12881
+ it('curried', () => {
12882
+ const result = removeIndex(1)([1, 2, 3])
12883
+
12884
+ result // $ExpectType number[]
12885
+ })
12886
+ })
12887
+ ```
12888
+
12889
+ </details>
12890
+
12891
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#removeIndex)
12892
+
12716
12893
  ### repeat
12717
12894
 
12718
12895
  ```typescript
@@ -15118,30 +15295,6 @@ test('happy', () => {
15118
15295
 
15119
15296
  </details>
15120
15297
 
15121
- <details>
15122
-
15123
- <summary><strong>TypeScript</strong> test</summary>
15124
-
15125
- ```typescript
15126
- import {toPairs} from 'rambda'
15127
-
15128
- const obj = {
15129
- a: 1,
15130
- b: 2,
15131
- c: [3, 4],
15132
- }
15133
-
15134
- describe('R.toPairs', () => {
15135
- it('happy', () => {
15136
- const result = toPairs(obj)
15137
-
15138
- result // $ExpectType (["b", number] | ["a", number] | ["c", number[]])[]
15139
- })
15140
- })
15141
- ```
15142
-
15143
- </details>
15144
-
15145
15298
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toPairs)
15146
15299
 
15147
15300
  ### toString
@@ -17173,13 +17326,13 @@ describe('R.zipObj', () => {
17173
17326
  it('happy', () => {
17174
17327
  // this is wrong since 24.10.2020 `@types/ramda` changes
17175
17328
  const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])
17176
- result // $ExpectType { b: number; a: number; c: number; d: number; }
17329
+ ;[result.a, result.b, result.c, result.d] // $ExpectType number[]
17177
17330
  })
17178
17331
  it('imported from @types/ramda', () => {
17179
17332
  const result = zipObj(['a', 'b', 'c'], [1, 2, 3])
17180
17333
  const curriedResult = zipObj(['a', 'b', 'c'])([1, 2, 3])
17181
- result // $ExpectType { b: number; a: number; c: number; }
17182
- curriedResult // $ExpectType { b: number; a: number; c: number; }
17334
+ ;[result.a, result.b, result.c] // $ExpectType number[]
17335
+ ;[curriedResult.a, curriedResult.b, curriedResult.c] // $ExpectType number[]
17183
17336
  })
17184
17337
  })
17185
17338
  ```
@@ -17299,6 +17452,40 @@ describe('R.zipWith', () => {
17299
17452
 
17300
17453
  ## ❯ CHANGELOG
17301
17454
 
17455
+ 8.4.0
17456
+
17457
+ - Add `R.dissocPath`
17458
+
17459
+ - Fix TS definitions of `R.head/R.last` and add missing handle of empty string
17460
+
17461
+ - Add `R.removeIndex` - method was before only in `Rambdax`, but now since `R.dissocPath` is using it, it is added to main library.
17462
+
17463
+ - Allow `R.omit` to pass numbers as part of properties to omit, i.e. `R.omit(['a', 1], {a: {1: 1, 2: 2}})`
17464
+
17465
+ - R.keys always returns strings - [MR #700](https://github.com/selfrefactor/rambda/pull/700)
17466
+
17467
+ - Improve `R.prepend/R.append` type interference - [MR #699](https://github.com/selfrefactor/rambda/pull/699)
17468
+
17469
+ - Change `R.reduce` TS definitions so index is always received - [MR #696](https://github.com/selfrefactor/rambda/pull/696)
17470
+
17471
+ - Functions as a type guard in `R.anyPass` TS definitions - [MR #695](https://github.com/selfrefactor/rambda/pull/695)
17472
+
17473
+ - Fix R.append's curried type - [MR #694](https://github.com/selfrefactor/rambda/pull/694)
17474
+
17475
+ - Fix cannot compare errors in `Deno` with `R.equals` - [Issue #704](https://github.com/selfrefactor/rambda/issues/704).
17476
+
17477
+ - Fix cannot compare `BigInt` with `R.equals`
17478
+
17479
+ 8.3.0
17480
+
17481
+ Add the following methods:
17482
+
17483
+ - binary
17484
+ - call
17485
+ - collectBy
17486
+ - comparator
17487
+ - composeWith
17488
+
17302
17489
  8.2.0
17303
17490
 
17304
17491
  Add the following methods:
@@ -17595,12 +17782,14 @@ Fix wrong versions in changelog
17595
17782
 
17596
17783
  ## ❯ Additional info
17597
17784
 
17598
- > Most influential contributors
17785
+ > Most influential contributors(in alphabetical order)
17599
17786
 
17600
17787
  - [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;
17601
17788
 
17602
17789
  - [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;
17603
17790
 
17791
+ - [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation
17792
+
17604
17793
  - [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;
17605
17794
 
17606
17795
  - [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;