rambda 8.3.0 → 8.5.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,13 +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 67 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
- - construct
104
- - constructN
105
- - dissocPath
106
104
  - dropRepeatsBy
107
105
  - empty
108
106
  - eqBy
@@ -154,8 +152,6 @@ Closing the issue is usually accompanied by publishing a new patch version of `R
154
152
  - symmetricDifferenceWith
155
153
  - andThen
156
154
  - toPairsIn
157
- - transduce
158
- - traverse
159
155
  - unary
160
156
  - uncurryN
161
157
  - unfold
@@ -167,6 +163,12 @@ Closing the issue is usually accompanied by publishing a new patch version of `R
167
163
  - thunkify
168
164
  - default
169
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
170
172
  </details>
171
173
 
172
174
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-missing-ramda-methods)
@@ -184,7 +186,7 @@ https://unpkg.com/rambda@CURRENT_VERSION/dist/rambda.umd.js
184
186
  - with deno
185
187
 
186
188
  ```
187
- 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";
188
190
  ```
189
191
 
190
192
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-install)
@@ -232,8 +234,8 @@ method | Rambda | Ramda | Lodash
232
234
  --- |--- | --- | ---
233
235
  *add* | 🚀 Fastest | 21.52% slower | 82.15% slower
234
236
  *adjust* | 8.48% slower | 🚀 Fastest | 🔳
235
- *all* | 🚀 Fastest | 1.81% slower | 🔳
236
- *allPass* | 🚀 Fastest | 91.09% slower | 🔳
237
+ *all* | 🚀 Fastest | 7.18% slower | 🔳
238
+ *allPass* | 🚀 Fastest | 88.25% slower | 🔳
237
239
  *allPass* | 🚀 Fastest | 98.56% slower | 🔳
238
240
  *and* | 🚀 Fastest | 89.09% slower | 🔳
239
241
  *any* | 🚀 Fastest | 92.87% slower | 45.82% slower
@@ -242,7 +244,7 @@ method | Rambda | Ramda | Lodash
242
244
  *applySpec* | 🚀 Fastest | 80.43% slower | 🔳
243
245
  *assoc* | 72.32% slower | 60.08% slower | 🚀 Fastest
244
246
  *clone* | 🚀 Fastest | 91.86% slower | 86.48% slower
245
- *compose* | 🚀 Fastest | 32.45% slower | 13.68% slower
247
+ *compose* | 6.07% slower | 16.89% slower | 🚀 Fastest
246
248
  *converge* | 78.63% slower | 🚀 Fastest | 🔳
247
249
  *curry* | 🚀 Fastest | 28.86% slower | 🔳
248
250
  *curryN* | 🚀 Fastest | 41.05% slower | 🔳
@@ -253,10 +255,10 @@ method | Rambda | Ramda | Lodash
253
255
  *filter* | 6.7% slower | 72.03% slower | 🚀 Fastest
254
256
  *find* | 🚀 Fastest | 85.14% slower | 42.65% slower
255
257
  *findIndex* | 🚀 Fastest | 86.48% slower | 72.27% slower
256
- *flatten* | 6.56% slower | 86.64% slower | 🚀 Fastest
258
+ *flatten* | 🚀 Fastest | 85.68% slower | 3.57% slower
257
259
  *ifElse* | 🚀 Fastest | 58.56% slower | 🔳
258
- *includes* | 🚀 Fastest | 84.63% slower | 🔳
259
- *indexOf* | 🚀 Fastest | 76.63% slower | 🔳
260
+ *includes* | 🚀 Fastest | 81.64% slower | 🔳
261
+ *indexOf* | 🚀 Fastest | 80.17% slower | 🔳
260
262
  *indexOf* | 🚀 Fastest | 82.2% slower | 🔳
261
263
  *init* | 🚀 Fastest | 92.24% slower | 13.3% slower
262
264
  *is* | 🚀 Fastest | 57.69% slower | 🔳
@@ -272,7 +274,7 @@ method | Rambda | Ramda | Lodash
272
274
  *over* | 🚀 Fastest | 56.23% slower | 🔳
273
275
  *path* | 37.81% slower | 77.81% slower | 🚀 Fastest
274
276
  *pick* | 🚀 Fastest | 19.07% slower | 80.2% slower
275
- *pipe* | 0.87% slower | 🚀 Fastest | 🔳
277
+ *pipe* | 🚀 Fastest | 0.11% slower | 🔳
276
278
  *prop* | 🚀 Fastest | 87.95% slower | 🔳
277
279
  *propEq* | 🚀 Fastest | 91.92% slower | 🔳
278
280
  *range* | 🚀 Fastest | 61.8% slower | 57.44% slower
@@ -288,8 +290,9 @@ method | Rambda | Ramda | Lodash
288
290
  *takeLast* | 🚀 Fastest | 93.39% slower | 19.22% slower
289
291
  *test* | 🚀 Fastest | 82.34% slower | 🔳
290
292
  *type* | 🚀 Fastest | 48.6% slower | 🔳
291
- *uniq* | 🚀 Fastest | 90.24% slower | 🔳
292
- *uniqWith* | 18.09% slower | 🚀 Fastest | 🔳
293
+ *uniq* | 🚀 Fastest | 84.9% slower | 🔳
294
+ *uniqBy* | 51.93% slower | 🚀 Fastest | 🔳
295
+ *uniqWith* | 8.29% slower | 🚀 Fastest | 🔳
293
296
  *uniqWith* | 14.23% slower | 🚀 Fastest | 🔳
294
297
  *update* | 🚀 Fastest | 52.35% slower | 🔳
295
298
  *view* | 🚀 Fastest | 76.15% slower | 🔳
@@ -925,6 +928,21 @@ describe('anyPass', () => {
925
928
  const filtered2 = xs.filter(pred)
926
929
  filtered2 // $ExpectType number[]
927
930
  })
931
+ it('functions as a type guard', () => {
932
+ const isString = (x: unknown): x is string => typeof x === 'string'
933
+ const isNumber = (x: unknown): x is number => typeof x === 'number'
934
+ const isBoolean = (x: unknown): x is boolean => typeof x === 'boolean'
935
+
936
+ const isStringNumberOrBoolean = anyPass([isString, isNumber, isBoolean])
937
+
938
+ isStringNumberOrBoolean // $ExpectType (input: unknown) => boolean
939
+
940
+ const aValue: unknown = 1
941
+
942
+ if (isStringNumberOrBoolean(aValue)) {
943
+ aValue // $ExpectType unknown
944
+ }
945
+ })
928
946
  })
929
947
  ```
930
948
 
@@ -1070,10 +1088,10 @@ test('happy', () => {
1070
1088
 
1071
1089
  ```typescript
1072
1090
 
1073
- append<T>(x: T, list: T[]): T[]
1091
+ append<T>(xToAppend: T, iterable: T[]): T[]
1074
1092
  ```
1075
1093
 
1076
- It adds element `x` at the end of `list`.
1094
+ It adds element `x` at the end of `iterable`.
1077
1095
 
1078
1096
  <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>
1079
1097
 
@@ -1082,8 +1100,10 @@ It adds element `x` at the end of `list`.
1082
1100
  <summary>All TypeScript definitions</summary>
1083
1101
 
1084
1102
  ```typescript
1085
- append<T>(x: T, list: T[]): T[];
1086
- append<T>(x: T): <T>(list: T[]) => T[];
1103
+ append<T>(xToAppend: T, iterable: T[]): T[];
1104
+ append<T, U>(xToAppend: T, iterable: IsFirstSubtypeOfSecond<T, U>[]) : U[];
1105
+ append<T>(xToAppend: T): <U>(iterable: IsFirstSubtypeOfSecond<T, U>[]) => U[];
1106
+ append<T>(xToAppend: T): (iterable: T[]) => T[];
1087
1107
  ```
1088
1108
 
1089
1109
  </details>
@@ -1114,7 +1134,8 @@ export function append(x, input){
1114
1134
  <summary><strong>Tests</strong></summary>
1115
1135
 
1116
1136
  ```javascript
1117
- import { append } from './append.js'
1137
+ // import { append } from './append.js'
1138
+ import { append } from 'ramda'
1118
1139
 
1119
1140
  test('happy', () => {
1120
1141
  expect(append('tests', [ 'write', 'more' ])).toEqual([
@@ -1140,20 +1161,62 @@ test('with strings', () => {
1140
1161
  <summary><strong>TypeScript</strong> test</summary>
1141
1162
 
1142
1163
  ```typescript
1143
- import {append} from 'rambda'
1164
+ import {append, prepend} from 'rambda'
1144
1165
 
1145
- const list = [1, 2, 3]
1166
+ const listOfNumbers = [1, 2, 3]
1167
+ const listOfNumbersAndStrings = [1, 'b', 3]
1146
1168
 
1147
- describe('R.append', () => {
1148
- it('happy', () => {
1149
- const result = append(4, list)
1169
+ describe('R.append/R.prepend', () => {
1170
+ describe("with the same primitive type as the array's elements", () => {
1171
+ it('uncurried', () => {
1172
+ // @ts-expect-error
1173
+ append('d', listOfNumbers)
1174
+ // @ts-expect-error
1175
+ prepend('d', listOfNumbers)
1176
+ append(4, listOfNumbers) // $ExpectType number[]
1177
+ prepend(4, listOfNumbers) // $ExpectType number[]
1178
+ })
1150
1179
 
1151
- result // $ExpectType number[]
1180
+ it('curried', () => {
1181
+ // @ts-expect-error
1182
+ append('d')(listOfNumbers)
1183
+ append(4)(listOfNumbers) // $ExpectType number[]
1184
+ prepend(4)(listOfNumbers) // $ExpectType number[]
1185
+ })
1152
1186
  })
1153
- it('curried', () => {
1154
- const result = append(4)(list)
1155
1187
 
1156
- result // $ExpectType number[]
1188
+ describe("with a subtype of the array's elements", () => {
1189
+ it('uncurried', () => {
1190
+ // @ts-expect-error
1191
+ append(true, listOfNumbersAndStrings)
1192
+ append(4, listOfNumbersAndStrings) // $ExpectType (string | number)[]
1193
+ prepend(4, listOfNumbersAndStrings) // $ExpectType (string | number)[]
1194
+ })
1195
+
1196
+ it('curried', () => {
1197
+ // @ts-expect-error
1198
+ append(true)(listOfNumbersAndStrings)
1199
+ append(4)(listOfNumbersAndStrings) // $ExpectType (string | number)[]
1200
+ prepend(4)(listOfNumbersAndStrings) // $ExpectType (string | number)[]
1201
+ })
1202
+ })
1203
+
1204
+ describe("expanding the type of the array's elements", () => {
1205
+ it('uncurried', () => {
1206
+ // @ts-expect-error
1207
+ append('d', listOfNumbers)
1208
+ append<string | number>('d', listOfNumbers) // $ExpectType (string | number)[]
1209
+ prepend<string | number>('d', listOfNumbers) // $ExpectType (string | number)[]
1210
+ })
1211
+
1212
+ it('curried', () => {
1213
+ // @ts-expect-error
1214
+ append('d')(listOfNumbers)
1215
+ const appendD = append('d')
1216
+ appendD<string | number>(listOfNumbers) // $ExpectType (string | number)[]
1217
+ const prependD = prepend('d')
1218
+ prependD<string | number>(listOfNumbers) // $ExpectType (string | number)[]
1219
+ })
1157
1220
  })
1158
1221
  })
1159
1222
  ```
@@ -1745,21 +1808,17 @@ assocPath<Output>(path: Path): (newValue: any) => (obj: object) => Output;
1745
1808
 
1746
1809
  ```javascript
1747
1810
  import { cloneList } from './_internals/cloneList.js'
1811
+ import { createPath } from './_internals/createPath.js'
1748
1812
  import { isArray } from './_internals/isArray.js'
1749
- import { isInteger } from './_internals/isInteger.js'
1750
- import { assoc } from './assoc.js'
1813
+ import { isIndexInteger } from './_internals/isInteger.js'
1814
+ import { assocFn } from './assoc.js'
1751
1815
  import { curry } from './curry.js'
1752
1816
 
1753
- function assocPathFn(
1817
+ export function assocPathFn(
1754
1818
  path, newValue, input
1755
1819
  ){
1756
- const pathArrValue =
1757
- typeof path === 'string' ?
1758
- path.split('.').map(x => isInteger(Number(x)) ? Number(x) : x) :
1759
- path
1760
- if (pathArrValue.length === 0){
1761
- return newValue
1762
- }
1820
+ const pathArrValue = createPath(path)
1821
+ if (pathArrValue.length === 0) return newValue
1763
1822
 
1764
1823
  const index = pathArrValue[ 0 ]
1765
1824
  if (pathArrValue.length > 1){
@@ -1769,7 +1828,7 @@ function assocPathFn(
1769
1828
  !input.hasOwnProperty(index)
1770
1829
 
1771
1830
  const nextInput = condition ?
1772
- isInteger(pathArrValue[ 1 ]) ?
1831
+ isIndexInteger(pathArrValue[ 1 ]) ?
1773
1832
  [] :
1774
1833
  {} :
1775
1834
  input[ index ]
@@ -1781,14 +1840,14 @@ function assocPathFn(
1781
1840
  )
1782
1841
  }
1783
1842
 
1784
- if (isInteger(index) && isArray(input)){
1843
+ if (isIndexInteger(index) && isArray(input)){
1785
1844
  const arr = cloneList(input)
1786
1845
  arr[ index ] = newValue
1787
1846
 
1788
1847
  return arr
1789
1848
  }
1790
1849
 
1791
- return assoc(
1850
+ return assocFn(
1792
1851
  index, newValue, input
1793
1852
  )
1794
1853
  }
@@ -1803,21 +1862,45 @@ export const assocPath = curry(assocPathFn)
1803
1862
  <summary><strong>Tests</strong></summary>
1804
1863
 
1805
1864
  ```javascript
1806
- import { assocPath } from './assocPath.js'
1865
+ import { assocPathFn } from './assocPath.js'
1866
+
1867
+ test.only('happy', () => {
1868
+ const path = 'a.c.1'
1869
+ const input = {
1870
+ a : {
1871
+ b : 1,
1872
+ c : [ 1, 2 ],
1873
+ },
1874
+ }
1875
+ assocPathFn(
1876
+ path, 3, input
1877
+ )
1878
+ expect(input).toEqual({
1879
+ a : {
1880
+ b : 1,
1881
+ c : [ 1, 2 ],
1882
+ },
1883
+ })
1884
+ })
1807
1885
 
1808
1886
  test('string can be used as path input', () => {
1809
1887
  const testObj = {
1810
1888
  a : [ { b : 1 }, { b : 2 } ],
1811
1889
  d : 3,
1812
1890
  }
1813
- const result = assocPath(
1891
+ const result1 = assocPathFn(
1892
+ [ 'a', 0, 'b' ], 10, testObj
1893
+ )
1894
+ const result2 = assocPathFn(
1814
1895
  'a.0.b', 10, testObj
1815
1896
  )
1897
+
1816
1898
  const expected = {
1817
1899
  a : [ { b : 10 }, { b : 2 } ],
1818
1900
  d : 3,
1819
1901
  }
1820
- expect(result).toEqual(expected)
1902
+ expect(result1).toEqual(expected)
1903
+ expect(result2).toEqual(expected)
1821
1904
  })
1822
1905
 
1823
1906
  test('difference with ramda - doesn\'t overwrite primitive values with keys in the path', () => {
@@ -2987,6 +3070,10 @@ It returns a new object that does not contain property `prop`.
2987
3070
 
2988
3071
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissoc)
2989
3072
 
3073
+ ### dissocPath
3074
+
3075
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissocPath)
3076
+
2990
3077
  ### divide
2991
3078
 
2992
3079
  <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>
@@ -3350,6 +3437,10 @@ describe('R.dropRepeats', () => {
3350
3437
 
3351
3438
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeats)
3352
3439
 
3440
+ ### dropRepeatsBy
3441
+
3442
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeatsBy)
3443
+
3353
3444
  ### dropRepeatsWith
3354
3445
 
3355
3446
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20list%20%3D%20%5B%7Ba%3A1%2Cb%3A2%7D%2C%20%7Ba%3A1%2Cb%3A3%7D%2C%20%7Ba%3A2%2C%20b%3A4%7D%5D%0Aconst%20result%20%3D%20R.dropRepeatsWith(R.prop('a')%2C%20list)%0A%0A%2F%2F%20%3D%3E%20%5B%7Ba%3A1%2Cb%3A2%7D%2C%20%7Ba%3A2%2C%20b%3A4%7D%5D">Try this <strong>R.dropRepeatsWith</strong> example in Rambda REPL</a>
@@ -3515,6 +3606,10 @@ describe('R.either', () => {
3515
3606
 
3516
3607
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#either)
3517
3608
 
3609
+ ### empty
3610
+
3611
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#empty)
3612
+
3518
3613
  ### endsWith
3519
3614
 
3520
3615
  ```typescript
@@ -3676,6 +3771,10 @@ describe('R.endsWith - string', () => {
3676
3771
 
3677
3772
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#endsWith)
3678
3773
 
3774
+ ### eqBy
3775
+
3776
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#eqBy)
3777
+
3679
3778
  ### eqProps
3680
3779
 
3681
3780
  It returns `true` if property `prop` in `obj1` is equal to property `prop` in `obj2` according to `R.equals`.
@@ -3715,43 +3814,39 @@ import { isArray } from './_internals/isArray.js'
3715
3814
  import { type } from './type.js'
3716
3815
 
3717
3816
  export function _lastIndexOf(valueToFind, list){
3718
- if (!isArray(list)){
3817
+ if (!isArray(list))
3719
3818
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3720
- }
3819
+
3721
3820
  const typeOfValue = type(valueToFind)
3722
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3821
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3723
3822
  return list.lastIndexOf(valueToFind)
3724
3823
 
3725
3824
  const { length } = list
3726
3825
  let index = length
3727
3826
  let foundIndex = -1
3728
3827
 
3729
- while (--index > -1 && foundIndex === -1){
3730
- if (equals(list[ index ], valueToFind)){
3828
+ while (--index > -1 && foundIndex === -1)
3829
+ if (equals(list[ index ], valueToFind))
3731
3830
  foundIndex = index
3732
- }
3733
- }
3734
3831
 
3735
3832
  return foundIndex
3736
3833
  }
3737
3834
 
3738
3835
  export function _indexOf(valueToFind, list){
3739
- if (!isArray(list)){
3836
+ if (!isArray(list))
3740
3837
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3741
- }
3838
+
3742
3839
  const typeOfValue = type(valueToFind)
3743
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3840
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3744
3841
  return list.indexOf(valueToFind)
3745
3842
 
3746
3843
  let index = -1
3747
3844
  let foundIndex = -1
3748
3845
  const { length } = list
3749
3846
 
3750
- while (++index < length && foundIndex === -1){
3751
- if (equals(list[ index ], valueToFind)){
3847
+ while (++index < length && foundIndex === -1)
3848
+ if (equals(list[ index ], valueToFind))
3752
3849
  foundIndex = index
3753
- }
3754
- }
3755
3850
 
3756
3851
  return foundIndex
3757
3852
  }
@@ -3759,17 +3854,16 @@ export function _indexOf(valueToFind, list){
3759
3854
  function _arrayFromIterator(iter){
3760
3855
  const list = []
3761
3856
  let next
3762
- while (!(next = iter.next()).done){
3857
+ while (!(next = iter.next()).done)
3763
3858
  list.push(next.value)
3764
- }
3765
3859
 
3766
3860
  return list
3767
3861
  }
3768
3862
 
3769
- function _equalsSets(a, b){
3770
- if (a.size !== b.size){
3863
+ function _compareSets(a, b){
3864
+ if (a.size !== b.size)
3771
3865
  return false
3772
- }
3866
+
3773
3867
  const aList = _arrayFromIterator(a.values())
3774
3868
  const bList = _arrayFromIterator(b.values())
3775
3869
 
@@ -3778,11 +3872,11 @@ function _equalsSets(a, b){
3778
3872
  return filtered.length === 0
3779
3873
  }
3780
3874
 
3781
- function parseError(maybeError){
3782
- const typeofError = maybeError.__proto__.toString()
3783
- if (![ 'Error', 'TypeError' ].includes(typeofError)) return []
3875
+ function compareErrors(a, b){
3876
+ if (a.message !== b.message) return false
3877
+ if (a.toString !== b.toString) return false
3784
3878
 
3785
- return [ typeofError, maybeError.message ]
3879
+ return a.toString() === b.toString()
3786
3880
  }
3787
3881
 
3788
3882
  function parseDate(maybeDate){
@@ -3803,40 +3897,36 @@ export function equals(a, b){
3803
3897
  const aType = type(a)
3804
3898
 
3805
3899
  if (aType !== type(b)) return false
3806
- if (aType === 'Function'){
3900
+ if (aType === 'Function')
3807
3901
  return a.name === undefined ? false : a.name === b.name
3808
- }
3809
3902
 
3810
- if ([ 'NaN', 'Undefined', 'Null' ].includes(aType)) return true
3903
+ if ([ 'NaN', 'Null', 'Undefined' ].includes(aType)) return true
3811
3904
 
3812
- if (aType === 'Number'){
3905
+ if ([ 'BigInt', 'Number' ].includes(aType)){
3813
3906
  if (Object.is(-0, a) !== Object.is(-0, b)) return false
3814
3907
 
3815
3908
  return a.toString() === b.toString()
3816
3909
  }
3817
3910
 
3818
- if ([ 'String', 'Boolean' ].includes(aType)){
3911
+ if ([ 'Boolean', 'String' ].includes(aType))
3819
3912
  return a.toString() === b.toString()
3820
- }
3821
3913
 
3822
3914
  if (aType === 'Array'){
3823
3915
  const aClone = Array.from(a)
3824
3916
  const bClone = Array.from(b)
3825
3917
 
3826
- if (aClone.toString() !== bClone.toString()){
3918
+ if (aClone.toString() !== bClone.toString())
3827
3919
  return false
3828
- }
3829
3920
 
3830
3921
  let loopArrayFlag = true
3831
3922
  aClone.forEach((aCloneInstance, aCloneIndex) => {
3832
- if (loopArrayFlag){
3923
+ if (loopArrayFlag)
3833
3924
  if (
3834
3925
  aCloneInstance !== bClone[ aCloneIndex ] &&
3835
3926
  !equals(aCloneInstance, bClone[ aCloneIndex ])
3836
- ){
3927
+ )
3837
3928
  loopArrayFlag = false
3838
- }
3839
- }
3929
+
3840
3930
  })
3841
3931
 
3842
3932
  return loopArrayFlag
@@ -3845,34 +3935,31 @@ export function equals(a, b){
3845
3935
  const aRegex = parseRegex(a)
3846
3936
  const bRegex = parseRegex(b)
3847
3937
 
3848
- if (aRegex[ 0 ]){
3938
+ if (aRegex[ 0 ])
3849
3939
  return bRegex[ 0 ] ? aRegex[ 1 ] === bRegex[ 1 ] : false
3850
- } else if (bRegex[ 0 ]) return false
3940
+ else if (bRegex[ 0 ]) return false
3851
3941
 
3852
3942
  const aDate = parseDate(a)
3853
3943
  const bDate = parseDate(b)
3854
3944
 
3855
- if (aDate[ 0 ]){
3945
+ if (aDate[ 0 ])
3856
3946
  return bDate[ 0 ] ? aDate[ 1 ] === bDate[ 1 ] : false
3857
- } else if (bDate[ 0 ]) return false
3947
+ else if (bDate[ 0 ]) return false
3858
3948
 
3859
- const aError = parseError(a)
3860
- const bError = parseError(b)
3949
+ if (a instanceof Error){
3950
+ if (!(b instanceof Error)) return false
3861
3951
 
3862
- if (aError[ 0 ]){
3863
- return bError[ 0 ] ?
3864
- aError[ 0 ] === bError[ 0 ] && aError[ 1 ] === bError[ 1 ] :
3865
- false
3866
- }
3867
- if (aType === 'Set'){
3868
- return _equalsSets(a, b)
3952
+ return compareErrors(a, b)
3869
3953
  }
3954
+
3955
+ if (aType === 'Set')
3956
+ return _compareSets(a, b)
3957
+
3870
3958
  if (aType === 'Object'){
3871
3959
  const aKeys = Object.keys(a)
3872
3960
 
3873
- if (aKeys.length !== Object.keys(b).length){
3961
+ if (aKeys.length !== Object.keys(b).length)
3874
3962
  return false
3875
- }
3876
3963
 
3877
3964
  let loopObjectFlag = true
3878
3965
  aKeys.forEach(aKeyInstance => {
@@ -3880,9 +3967,9 @@ export function equals(a, b){
3880
3967
  const aValue = a[ aKeyInstance ]
3881
3968
  const bValue = b[ aKeyInstance ]
3882
3969
 
3883
- if (aValue !== bValue && !equals(aValue, bValue)){
3970
+ if (aValue !== bValue && !equals(aValue, bValue))
3884
3971
  loopObjectFlag = false
3885
- }
3972
+
3886
3973
  }
3887
3974
  })
3888
3975
 
@@ -3969,6 +4056,7 @@ test('new Error', () => {
3969
4056
  expect(equals(new Error('XXX'), new Error('YYY'))).toBeFalse()
3970
4057
  expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3971
4058
  expect(equals(new Error('XXX'), new TypeError('YYY'))).toBeFalse()
4059
+ expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3972
4060
  })
3973
4061
 
3974
4062
  test('with dates', () => {
@@ -3997,8 +4085,8 @@ test('ramda spec', () => {
3997
4085
  b : 3,
3998
4086
  },
3999
4087
  {
4000
- b : 3,
4001
4088
  a : 2,
4089
+ b : 3,
4002
4090
  })).toBeTrue()
4003
4091
 
4004
4092
  expect(equals({
@@ -4094,8 +4182,8 @@ test('various examples', () => {
4094
4182
  b : 2,
4095
4183
  },
4096
4184
  {
4097
- b : 2,
4098
4185
  a : 1,
4186
+ b : 2,
4099
4187
  })).toBeTrue()
4100
4188
 
4101
4189
  expect(equals({
@@ -4121,8 +4209,8 @@ test('various examples', () => {
4121
4209
  b : 2,
4122
4210
  },
4123
4211
  {
4124
- b : 2,
4125
4212
  a : 1,
4213
+ b : 2,
4126
4214
  c : 3,
4127
4215
  })).toBeFalse()
4128
4216
 
@@ -4134,8 +4222,8 @@ test('various examples', () => {
4134
4222
  },
4135
4223
  {
4136
4224
  x : {
4137
- b : 2,
4138
4225
  a : 1,
4226
+ b : 2,
4139
4227
  c : 3,
4140
4228
  },
4141
4229
  })).toBeFalse()
@@ -4145,8 +4233,8 @@ test('various examples', () => {
4145
4233
  b : 2,
4146
4234
  },
4147
4235
  {
4148
- b : 3,
4149
4236
  a : 1,
4237
+ b : 3,
4150
4238
  })).toBeFalse()
4151
4239
 
4152
4240
  expect(equals({ a : { b : { c : 1 } } }, { a : { b : { c : 1 } } })).toBeTrue()
@@ -4195,26 +4283,32 @@ test('with negative zero', () => {
4195
4283
  expect(equals(-0, 1)).toBeFalse()
4196
4284
  })
4197
4285
 
4198
- const possibleInputs = variousTypes
4286
+ test('with big int', () => {
4287
+ const a = BigInt(9007199254740991)
4288
+ const b = BigInt(9007199254740991)
4289
+ const c = BigInt(7007199254740991)
4290
+ expect(equals(a, b)).toBeTrue()
4291
+ expect(equals(a, c)).toBeFalse()
4292
+ })
4199
4293
 
4200
4294
  describe('brute force', () => {
4201
4295
  compareCombinations({
4202
- fn : equals,
4203
- fnRamda : equalsRamda,
4204
- firstInput : possibleInputs,
4205
- secondInput : possibleInputs,
4206
- callback : errorsCounters => {
4296
+ callback : errorsCounters => {
4207
4297
  expect(errorsCounters).toMatchInlineSnapshot(`
4208
- {
4209
- "ERRORS_MESSAGE_MISMATCH": 0,
4210
- "ERRORS_TYPE_MISMATCH": 0,
4211
- "RESULTS_MISMATCH": 5,
4212
- "SHOULD_NOT_THROW": 4,
4213
- "SHOULD_THROW": 0,
4214
- "TOTAL_TESTS": 289,
4215
- }
4216
- `)
4298
+ {
4299
+ "ERRORS_MESSAGE_MISMATCH": 0,
4300
+ "ERRORS_TYPE_MISMATCH": 0,
4301
+ "RESULTS_MISMATCH": 8,
4302
+ "SHOULD_NOT_THROW": 0,
4303
+ "SHOULD_THROW": 0,
4304
+ "TOTAL_TESTS": 289,
4305
+ }
4306
+ `)
4217
4307
  },
4308
+ firstInput : variousTypes,
4309
+ fn : equals,
4310
+ fnRamda : equalsRamda,
4311
+ secondInput : variousTypes,
4218
4312
  })
4219
4313
  })
4220
4314
  ```
@@ -5339,36 +5433,46 @@ forEach<T, U>(fn: ObjectIterator<T, void>): (list: Dictionary<T>) => Dictionary<
5339
5433
  import { isArray } from './_internals/isArray.js'
5340
5434
  import { keys } from './_internals/keys.js'
5341
5435
 
5342
- export function forEach(fn, list){
5343
- if (arguments.length === 1) return _list => forEach(fn, _list)
5436
+ export function forEachObjIndexedFn(fn, obj){
5437
+ let index = 0
5438
+ const listKeys = keys(obj)
5439
+ const len = listKeys.length
5344
5440
 
5345
- if (list === undefined){
5346
- return
5441
+ while (index < len){
5442
+ const key = listKeys[ index ]
5443
+ fn(
5444
+ obj[ key ], key, obj
5445
+ )
5446
+ index++
5347
5447
  }
5348
5448
 
5349
- if (isArray(list)){
5350
- let index = 0
5351
- const len = list.length
5449
+ return obj
5450
+ }
5352
5451
 
5353
- while (index < len){
5354
- fn(list[ index ])
5355
- index++
5356
- }
5357
- } else {
5452
+ export function forEachObjIndexed(fn, list){
5453
+ if (arguments.length === 1) return _list => forEachObjIndexed(fn, _list)
5454
+
5455
+ if (list === undefined) return
5456
+
5457
+ return forEachObjIndexedFn(fn, list)
5458
+ }
5459
+
5460
+ export function forEach(fn, iterable){
5461
+ if (arguments.length === 1) return _list => forEach(fn, _list)
5462
+
5463
+ if (iterable === undefined) return
5464
+
5465
+ if (isArray(iterable)){
5358
5466
  let index = 0
5359
- const listKeys = keys(list)
5360
- const len = listKeys.length
5467
+ const len = iterable.length
5361
5468
 
5362
5469
  while (index < len){
5363
- const key = listKeys[ index ]
5364
- fn(
5365
- list[ key ], key, list
5366
- )
5470
+ fn(iterable[ index ])
5367
5471
  index++
5368
5472
  }
5369
- }
5473
+ } else return forEachObjIndexedFn(fn, iterable)
5370
5474
 
5371
- return list
5475
+ return iterable
5372
5476
  }
5373
5477
  ```
5374
5478
 
@@ -5499,6 +5603,10 @@ describe('R.forEach with objects', () => {
5499
5603
 
5500
5604
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#forEach)
5501
5605
 
5606
+ ### forEachObjIndexed
5607
+
5608
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#forEachObjIndexed)
5609
+
5502
5610
  ### fromPairs
5503
5611
 
5504
5612
  It transforms a `listOfPairs` to an object.
@@ -5716,7 +5824,7 @@ describe('R.hasPath', () => {
5716
5824
 
5717
5825
  ```typescript
5718
5826
 
5719
- head(input: string): string
5827
+ head(str: string): string
5720
5828
  ```
5721
5829
 
5722
5830
  It returns the first element of list or string `input`.
@@ -5728,8 +5836,10 @@ It returns the first element of list or string `input`.
5728
5836
  <summary>All TypeScript definitions</summary>
5729
5837
 
5730
5838
  ```typescript
5731
- head(input: string): string;
5732
- head(emptyList: []): undefined;
5839
+ head(str: string): string;
5840
+ head(str: ''): undefined;
5841
+ head<T>(list: never[]): undefined;
5842
+ head<T extends unknown[]>(array: T): FirstArrayElement<T>
5733
5843
  head<T extends readonly unknown[]>(array: T): FirstArrayElement<T>
5734
5844
  ```
5735
5845
 
@@ -5771,34 +5881,46 @@ test('head', () => {
5771
5881
  <summary><strong>TypeScript</strong> test</summary>
5772
5882
 
5773
5883
  ```typescript
5774
- import {mixedList, mixedListConst} from '_internals/typescriptTestUtils'
5775
- import {head} from 'rambda'
5884
+ import {
5885
+ emptyList,
5886
+ emptyString,
5887
+ mixedList,
5888
+ mixedListConst,
5889
+ numberList,
5890
+ numberListConst,
5891
+ string,
5892
+ } from '_internals/typescriptTestUtils'
5893
+ import {head, last} from 'rambda'
5776
5894
 
5777
5895
  describe('R.head', () => {
5778
5896
  it('string', () => {
5779
- const result = head('foo')
5780
- result // $ExpectType string
5897
+ head(string) // $ExpectType string
5898
+ last(string) // $ExpectType string
5781
5899
  })
5782
- it('array', () => {
5783
- const result = head([1, 2, 3])
5784
- result // $ExpectType number
5785
- })
5786
- it('mixed', () => {
5787
- const result = head(mixedList)
5788
- result // $ExpectType string | number
5900
+ it('empty string', () => {
5901
+ head(emptyString) // $ExpectType undefined
5902
+ last(emptyString) // $ExpectType undefined
5789
5903
  })
5790
- it('mixed const', () => {
5791
- const result = head(mixedListConst)
5792
- result // $ExpectType 1
5904
+ it('array', () => {
5905
+ head(numberList) // $ExpectType number
5906
+ head(numberListConst) // $ExpectType 1
5907
+
5908
+ last(numberList) // $ExpectType number
5909
+ last(numberListConst) // $ExpectType 3
5793
5910
  })
5794
- it('empty array - case 1', () => {
5795
- const result = head([])
5796
- result // $ExpectType undefined
5911
+ it('empty array', () => {
5912
+ const list = [] as const
5913
+ head(emptyList) // $ExpectType undefined
5914
+ head(list) // $ExpectType never
5915
+ last(emptyList) // $ExpectType undefined
5916
+ last(list) // $ExpectType never
5797
5917
  })
5798
- it('empty array - case 2', () => {
5799
- const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
5800
- const result = head(list)
5801
- result // $ExpectType string
5918
+
5919
+ it('mixed', () => {
5920
+ head(mixedList) // $ExpectType string | number
5921
+ head(mixedListConst) // $ExpectType 1
5922
+ last(mixedList) // $ExpectType string | number
5923
+ last(mixedListConst) // $ExpectType "bar"
5802
5924
  })
5803
5925
  })
5804
5926
  ```
@@ -6693,7 +6815,7 @@ describe('R.juxt', () => {
6693
6815
 
6694
6816
  ```typescript
6695
6817
 
6696
- keys<T extends object>(x: T): (keyof T)[]
6818
+ keys<T extends object>(x: T): (keyof T & string)[]
6697
6819
  ```
6698
6820
 
6699
6821
  It applies `Object.keys` over `x` and returns its keys.
@@ -6705,7 +6827,7 @@ It applies `Object.keys` over `x` and returns its keys.
6705
6827
  <summary>All TypeScript definitions</summary>
6706
6828
 
6707
6829
  ```typescript
6708
- keys<T extends object>(x: T): (keyof T)[];
6830
+ keys<T extends object>(x: T): (keyof T & string)[];
6709
6831
  keys<T>(x: T): string[];
6710
6832
  ```
6711
6833
 
@@ -6737,32 +6859,13 @@ test('happy', () => {
6737
6859
 
6738
6860
  </details>
6739
6861
 
6740
- <details>
6741
-
6742
- <summary><strong>TypeScript</strong> test</summary>
6743
-
6744
- ```typescript
6745
- import {keys} from 'rambda'
6746
-
6747
- const obj = {a: 1, b: 2}
6748
-
6749
- describe('R.keys', () => {
6750
- it('happy', () => {
6751
- const result = keys(obj)
6752
- result // $ExpectType ("b" | "a")[]
6753
- })
6754
- })
6755
- ```
6756
-
6757
- </details>
6758
-
6759
6862
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#keys)
6760
6863
 
6761
6864
  ### last
6762
6865
 
6763
6866
  ```typescript
6764
6867
 
6765
- last(input: string): string
6868
+ last(str: ''): undefined
6766
6869
  ```
6767
6870
 
6768
6871
  It returns the last element of `input`, as the `input` can be either a string or an array.
@@ -6774,8 +6877,10 @@ It returns the last element of `input`, as the `input` can be either a string or
6774
6877
  <summary>All TypeScript definitions</summary>
6775
6878
 
6776
6879
  ```typescript
6777
- last(input: string): string;
6778
- last(emptyList: []): undefined;
6880
+ last(str: ''): undefined;
6881
+ last(str: string): string;
6882
+ last(list: never[]): undefined;
6883
+ last<T extends unknown[]>(array: T): LastArrayElement<T>
6779
6884
  last<T extends readonly unknown[]>(array: T): LastArrayElement<T>
6780
6885
  ```
6781
6886
 
@@ -6817,45 +6922,6 @@ test('with string', () => {
6817
6922
 
6818
6923
  </details>
6819
6924
 
6820
- <details>
6821
-
6822
- <summary><strong>TypeScript</strong> test</summary>
6823
-
6824
- ```typescript
6825
- import {mixedList, mixedListConst} from '_internals/typescriptTestUtils'
6826
- import {last} from 'rambda'
6827
-
6828
- describe('R.last', () => {
6829
- it('string', () => {
6830
- const result = last('foo')
6831
- result // $ExpectType string
6832
- })
6833
- it('array', () => {
6834
- const result = last([1, 2, 3])
6835
- result // $ExpectType number
6836
- })
6837
- it('mixed', () => {
6838
- const result = last(mixedList)
6839
- result // $ExpectType string | number
6840
- })
6841
- it('mixed const', () => {
6842
- const result = last(mixedListConst)
6843
- result // $ExpectType "bar"
6844
- })
6845
- it('empty array - case 1', () => {
6846
- const result = last([])
6847
- result // $ExpectType undefined
6848
- })
6849
- it('empty array - case 2', () => {
6850
- const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
6851
- const result = last(list)
6852
- result // $ExpectType string
6853
- })
6854
- })
6855
- ```
6856
-
6857
- </details>
6858
-
6859
6925
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#last)
6860
6926
 
6861
6927
  ### lastIndexOf
@@ -8739,7 +8805,7 @@ mergeWith<Output>(fn: (x: any, z: any) => any): <U, V>(a: U, b: V) => Output;
8739
8805
  ```javascript
8740
8806
  import { curry } from './curry.js'
8741
8807
 
8742
- function mergeWithFn(
8808
+ export function mergeWithFn(
8743
8809
  mergeFn, aInput, bInput
8744
8810
  ){
8745
8811
  const a = aInput ?? {}
@@ -8747,21 +8813,15 @@ function mergeWithFn(
8747
8813
  const willReturn = {}
8748
8814
 
8749
8815
  Object.keys(a).forEach(key => {
8750
- if (b[ key ] === undefined){
8751
- willReturn[ key ] = a[ key ]
8752
- } else {
8753
- willReturn[ key ] = mergeFn(a[ key ], b[ key ])
8754
- }
8816
+ if (b[ key ] === undefined) willReturn[ key ] = a[ key ]
8817
+ else willReturn[ key ] = mergeFn(a[ key ], b[ key ])
8755
8818
  })
8756
8819
 
8757
8820
  Object.keys(b).forEach(key => {
8758
8821
  if (willReturn[ key ] !== undefined) return
8759
8822
 
8760
- if (a[ key ] === undefined){
8761
- willReturn[ key ] = b[ key ]
8762
- } else {
8763
- willReturn[ key ] = mergeFn(a[ key ], b[ key ])
8764
- }
8823
+ if (a[ key ] === undefined) willReturn[ key ] = b[ key ]
8824
+ else willReturn[ key ] = mergeFn(a[ key ], b[ key ])
8765
8825
  })
8766
8826
 
8767
8827
  return willReturn
@@ -8778,10 +8838,10 @@ export const mergeWith = curry(mergeWithFn)
8778
8838
 
8779
8839
  ```javascript
8780
8840
  import { concat } from './concat.js'
8781
- import { mergeWith } from './mergeWith.js'
8841
+ import { mergeWithFn } from './mergeWith.js'
8782
8842
 
8783
8843
  test('happy', () => {
8784
- const result = mergeWith(
8844
+ const result = mergeWithFn(
8785
8845
  concat,
8786
8846
  {
8787
8847
  a : true,
@@ -8794,8 +8854,8 @@ test('happy', () => {
8794
8854
  )
8795
8855
  const expected = {
8796
8856
  a : true,
8797
- values : [ 10, 20, 15, 35 ],
8798
8857
  b : true,
8858
+ values : [ 10, 20, 15, 35 ],
8799
8859
  }
8800
8860
  expect(result).toEqual(expected)
8801
8861
  })
@@ -8803,31 +8863,31 @@ test('happy', () => {
8803
8863
  // https://github.com/ramda/ramda/pull/3222/files#diff-d925d9188b478d2f1d4b26012c6dddac374f9e9d7a336604d654b9a113bfc857
8804
8864
  describe('acts as if nil values are simply empty objects', () => {
8805
8865
  it('if the first object is nil and the second empty', () => {
8806
- expect(mergeWith(
8866
+ expect(mergeWithFn(
8807
8867
  concat, undefined, {}
8808
8868
  )).toEqual({})
8809
8869
  })
8810
8870
 
8811
8871
  it('if the first object is empty and the second nil', () => {
8812
- expect(mergeWith(
8872
+ expect(mergeWithFn(
8813
8873
  concat, {}, null
8814
8874
  )).toEqual({})
8815
8875
  })
8816
8876
 
8817
8877
  it('if both objects are nil', () => {
8818
- expect(mergeWith(
8878
+ expect(mergeWithFn(
8819
8879
  concat, undefined, null
8820
8880
  )).toEqual({})
8821
8881
  })
8822
8882
 
8823
8883
  it('if the first object is not empty and the second is nil', () => {
8824
- expect(mergeWith(
8884
+ expect(mergeWithFn(
8825
8885
  concat, { a : 'a' }, null
8826
8886
  )).toEqual({ a : 'a' })
8827
8887
  })
8828
8888
 
8829
8889
  it('if the first object is nil and the second is not empty', () => {
8830
- expect(mergeWith(
8890
+ expect(mergeWithFn(
8831
8891
  concat, undefined, { a : 'a' }
8832
8892
  )).toEqual({ a : 'a' })
8833
8893
  })
@@ -9634,22 +9694,20 @@ omit<T>(propsToOmit: string): (obj: object) => T;
9634
9694
 
9635
9695
  ```javascript
9636
9696
  import { createPath } from './_internals/createPath.js'
9697
+ import { includes } from './_internals/includes.js'
9637
9698
 
9638
9699
  export function omit(propsToOmit, obj){
9639
9700
  if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)
9640
9701
 
9641
- if (obj === null || obj === undefined){
9702
+ if (obj === null || obj === undefined)
9642
9703
  return undefined
9643
- }
9644
9704
 
9645
9705
  const propsToOmitValue = createPath(propsToOmit, ',')
9646
9706
  const willReturn = {}
9647
9707
 
9648
- for (const key in obj){
9649
- if (!propsToOmitValue.includes(key)){
9708
+ for (const key in obj)
9709
+ if (!includes(key, propsToOmitValue))
9650
9710
  willReturn[ key ] = obj[ key ]
9651
- }
9652
- }
9653
9711
 
9654
9712
  return willReturn
9655
9713
  }
@@ -9678,18 +9736,17 @@ test('with string as condition', () => {
9678
9736
  expect(resultCurry).toEqual(expectedResult)
9679
9737
  })
9680
9738
 
9681
- test('with null', () => {
9682
- expect(omit('a,b', null)).toBeUndefined()
9739
+ test.only('with number as property to omit', () => {
9740
+ const obj = {
9741
+ 1 : 1,
9742
+ b : 2,
9743
+ }
9744
+ const result = omit([ 1 ], obj)
9745
+ expect(result).toEqual({ b : 2 })
9683
9746
  })
9684
9747
 
9685
- test('doesn\'t work with number as property', () => {
9686
- expect(omit([ 42 ], {
9687
- a : 1,
9688
- 42 : 2,
9689
- })).toEqual({
9690
- 42 : 2,
9691
- a : 1,
9692
- })
9748
+ test('with null', () => {
9749
+ expect(omit('a,b', null)).toBeUndefined()
9693
9750
  })
9694
9751
 
9695
9752
  test('happy', () => {
@@ -10053,10 +10110,19 @@ The name comes from the fact that you partially inject the inputs.
10053
10110
  partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T;
10054
10111
  partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0, V1]): (x2: V2) => T;
10055
10112
  partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0]): (x1: V1, x2: V2) => T;
10056
- partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1, V2]): (x2: V3) => T;
10057
- partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1]): (x2: V2, x3: V3) => T;
10058
- 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;
10059
- partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
10113
+ partial<V0, V1, V2, V3, T>(
10114
+ fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T,
10115
+ args: [V0, V1, V2],
10116
+ ): (x2: V3) => T;
10117
+ partial<V0, V1, V2, V3, T>(
10118
+ fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T,
10119
+ args: [V0, V1],
10120
+ ): (x2: V2, x3: V3) => T;
10121
+ partial<V0, V1, V2, V3, T>(
10122
+ fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T,
10123
+ args: [V0],
10124
+ ): (x1: V1, x2: V2, x3: V3) => T;
10125
+ partial<T>(fn: (...a: any[]) => T, args: any[]): (...a: any[]) => T;
10060
10126
  ```
10061
10127
 
10062
10128
  </details>
@@ -10066,15 +10132,21 @@ partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
10066
10132
  <summary><strong>R.partial</strong> source</summary>
10067
10133
 
10068
10134
  ```javascript
10135
+ import { isArray } from './_internals/isArray.js'
10136
+
10069
10137
  export function partial(fn, ...args){
10070
10138
  const len = fn.length
10071
10139
 
10140
+ // If a single array argument is given, those are the args (a la Ramda).
10141
+ // Otherwise, the variadic arguments are the args.
10142
+ const argList = args.length === 1 && isArray(args[0]) ? args[0] : args
10143
+
10072
10144
  return (...rest) => {
10073
- if (args.length + rest.length >= len){
10074
- return fn(...args, ...rest)
10145
+ if (argList.length + rest.length >= len){
10146
+ return fn(...argList, ...rest)
10075
10147
  }
10076
10148
 
10077
- return partial(fn, ...[ ...args, ...rest ])
10149
+ return partial(fn, ...[ ...argList, ...rest ])
10078
10150
  }
10079
10151
  }
10080
10152
  ```
@@ -10092,7 +10164,7 @@ import { type } from './type.js'
10092
10164
  const greet = (
10093
10165
  salutation, title, firstName, lastName
10094
10166
  ) =>
10095
- salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!'
10167
+ [salutation, title, firstName, lastName]
10096
10168
 
10097
10169
  test('happy', () => {
10098
10170
  const canPassAnyNumberOfArguments = partial(
@@ -10104,8 +10176,8 @@ test('happy', () => {
10104
10176
 
10105
10177
  expect(type(fn)).toBe('Function')
10106
10178
 
10107
- expect(fn('bar')).toBe('Hello, Ms. foo bar!')
10108
- expect(sayHelloRamda('foo', 'bar')).toBe('Hello, Ms. foo bar!')
10179
+ expect(fn('bar')).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10180
+ expect(sayHelloRamda('foo', 'bar')).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10109
10181
  })
10110
10182
 
10111
10183
  test('extra arguments are ignored', () => {
@@ -10118,7 +10190,7 @@ test('extra arguments are ignored', () => {
10118
10190
 
10119
10191
  expect(fn(
10120
10192
  'bar', 1, 2
10121
- )).toBe('Hello, Ms. foo bar!')
10193
+ )).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10122
10194
  })
10123
10195
 
10124
10196
  test('when array is input', () => {
@@ -10146,7 +10218,7 @@ test('ramda spec', () => {
10146
10218
  const sayHello = partial(greet, 'Hello')
10147
10219
  const sayHelloToMs = partial(sayHello, 'Ms.')
10148
10220
 
10149
- expect(sayHelloToMs('Jane', 'Jones')).toBe('Hello, Ms. Jane Jones!')
10221
+ expect(sayHelloToMs('Jane', 'Jones')).toStrictEqual(['Hello', 'Ms.', 'Jane', 'Jones'])
10150
10222
  })
10151
10223
  ```
10152
10224
 
@@ -10161,19 +10233,24 @@ import {partial} from 'rambda'
10161
10233
 
10162
10234
  describe('R.partial', () => {
10163
10235
  it('happy', () => {
10164
- function greet(
10165
- salutation: string,
10166
- title: string,
10167
- firstName: string,
10168
- lastName: string
10236
+ function fn(
10237
+ aString: string,
10238
+ aNumber: number,
10239
+ aBoolean: boolean,
10240
+ aNull: null
10169
10241
  ) {
10170
- return `${salutation}, ${title} ${firstName} ${lastName}!`
10242
+ return {aString, aNumber, aBoolean, aNull}
10171
10243
  }
10172
10244
 
10173
- const sayHello = partial(greet, ['Hello'])
10174
- const sayHelloToMs = partial(sayHello, ['Ms.'])
10175
- const result = sayHelloToMs('Jane', 'Jones')
10176
- result // $ExpectType string
10245
+ // @ts-expect-error
10246
+ partial(fn, 1)
10247
+
10248
+ const fn1 = partial(fn, ['a'])
10249
+ partial(fn1, ['b'])
10250
+
10251
+ const fn2 = partial(fn1, [2])
10252
+ const result = fn2(true, null)
10253
+ result // $ExpectType { aString: string; aNumber: number; aBoolean: boolean; aNull: null; }
10177
10254
  })
10178
10255
  })
10179
10256
  ```
@@ -11318,10 +11395,10 @@ test('works with list as input and number as props - props to pick is a string',
11318
11395
  test('with symbol', () => {
11319
11396
  const symbolProp = Symbol('s')
11320
11397
  expect(pick([ symbolProp ], { [ symbolProp ] : 'a' })).toMatchInlineSnapshot(`
11321
- {
11322
- Symbol(s): "a",
11323
- }
11324
- `)
11398
+ {
11399
+ Symbol(s): "a",
11400
+ }
11401
+ `)
11325
11402
  })
11326
11403
  ```
11327
11404
 
@@ -11674,7 +11751,7 @@ describe('R.pluck', () => {
11674
11751
 
11675
11752
  ```typescript
11676
11753
 
11677
- prepend<T>(x: T, input: T[]): T[]
11754
+ prepend<T>(xToPrepend: T, iterable: T[]): T[]
11678
11755
  ```
11679
11756
 
11680
11757
  It adds element `x` at the beginning of `list`.
@@ -11686,8 +11763,10 @@ It adds element `x` at the beginning of `list`.
11686
11763
  <summary>All TypeScript definitions</summary>
11687
11764
 
11688
11765
  ```typescript
11689
- prepend<T>(x: T, input: T[]): T[];
11690
- prepend<T>(x: T): (input: T[]) => T[];
11766
+ prepend<T>(xToPrepend: T, iterable: T[]): T[];
11767
+ prepend<T, U>(xToPrepend: T, iterable: IsFirstSubtypeOfSecond<T, U>[]) : U[];
11768
+ prepend<T>(xToPrepend: T): <U>(iterable: IsFirstSubtypeOfSecond<T, U>[]) => U[];
11769
+ prepend<T>(xToPrepend: T): (iterable: T[]) => T[];
11691
11770
  ```
11692
11771
 
11693
11772
  </details>
@@ -11735,31 +11814,6 @@ test('with string instead of array', () => {
11735
11814
 
11736
11815
  </details>
11737
11816
 
11738
- <details>
11739
-
11740
- <summary><strong>TypeScript</strong> test</summary>
11741
-
11742
- ```typescript
11743
- import {prepend} from 'rambda'
11744
-
11745
- const list = [1, 2, 3]
11746
-
11747
- describe('R.prepend', () => {
11748
- it('happy', () => {
11749
- const result = prepend(4, list)
11750
-
11751
- result // $ExpectType number[]
11752
- })
11753
- it('curried', () => {
11754
- const result = prepend(4)(list)
11755
-
11756
- result // $ExpectType number[]
11757
- })
11758
- })
11759
- ```
11760
-
11761
- </details>
11762
-
11763
11817
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prepend)
11764
11818
 
11765
11819
  ### product
@@ -12721,6 +12775,96 @@ describe('R.reject with objects', () => {
12721
12775
 
12722
12776
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reject)
12723
12777
 
12778
+ ### removeIndex
12779
+
12780
+ ```typescript
12781
+
12782
+ removeIndex<T>(index: number, list: T[]): T[]
12783
+ ```
12784
+
12785
+ It returns a copy of `list` input with removed `index`.
12786
+
12787
+ <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>
12788
+
12789
+ <details>
12790
+
12791
+ <summary>All TypeScript definitions</summary>
12792
+
12793
+ ```typescript
12794
+ removeIndex<T>(index: number, list: T[]): T[];
12795
+ removeIndex(index: number): <T>(list: T[]) => T[];
12796
+ ```
12797
+
12798
+ </details>
12799
+
12800
+ <details>
12801
+
12802
+ <summary><strong>R.removeIndex</strong> source</summary>
12803
+
12804
+ ```javascript
12805
+ export function removeIndex(index, list){
12806
+ if (arguments.length === 1) return _list => removeIndex(index, _list)
12807
+ if (index <= 0) return list.slice(1)
12808
+ if (index >= list.length - 1) return list.slice(0, list.length - 1)
12809
+
12810
+ return [ ...list.slice(0, index), ...list.slice(index + 1) ]
12811
+ }
12812
+ ```
12813
+
12814
+ </details>
12815
+
12816
+ <details>
12817
+
12818
+ <summary><strong>Tests</strong></summary>
12819
+
12820
+ ```javascript
12821
+ import { removeIndex } from './removeIndex.js'
12822
+
12823
+ const list = [ 1, 2, 3, 4 ]
12824
+
12825
+ test('first or before first index', () => {
12826
+ expect(removeIndex(-2, list)).toEqual([ 2, 3, 4 ])
12827
+ expect(removeIndex(-2)(list)).toEqual([ 2, 3, 4 ])
12828
+ })
12829
+
12830
+ test('last or after last index', () => {
12831
+ expect(removeIndex(4, list)).toEqual([ 1, 2, 3 ])
12832
+ expect(removeIndex(10, list)).toEqual([ 1, 2, 3 ])
12833
+ })
12834
+
12835
+ test('middle index', () => {
12836
+ expect(removeIndex(1, list)).toEqual([ 1, 3, 4 ])
12837
+ expect(removeIndex(2, list)).toEqual([ 1, 2, 4 ])
12838
+ })
12839
+ ```
12840
+
12841
+ </details>
12842
+
12843
+ <details>
12844
+
12845
+ <summary><strong>TypeScript</strong> test</summary>
12846
+
12847
+ ```typescript
12848
+ import {removeIndex} from 'rambda'
12849
+
12850
+ describe('R.removeIndex', () => {
12851
+ it('happy', () => {
12852
+ const result = removeIndex(1, [1, 2, 3])
12853
+
12854
+ result // $ExpectType number[]
12855
+ })
12856
+ it('curried', () => {
12857
+ const result = removeIndex(1)([1, 2, 3])
12858
+
12859
+ result // $ExpectType number[]
12860
+ })
12861
+ })
12862
+ ```
12863
+
12864
+ </details>
12865
+
12866
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#removeIndex)
12867
+
12724
12868
  ### repeat
12725
12869
 
12726
12870
  ```typescript
@@ -15126,30 +15270,6 @@ test('happy', () => {
15126
15270
 
15127
15271
  </details>
15128
15272
 
15129
- <details>
15130
-
15131
- <summary><strong>TypeScript</strong> test</summary>
15132
-
15133
- ```typescript
15134
- import {toPairs} from 'rambda'
15135
-
15136
- const obj = {
15137
- a: 1,
15138
- b: 2,
15139
- c: [3, 4],
15140
- }
15141
-
15142
- describe('R.toPairs', () => {
15143
- it('happy', () => {
15144
- const result = toPairs(obj)
15145
-
15146
- result // $ExpectType (["b", number] | ["a", number] | ["c", number[]])[]
15147
- })
15148
- })
15149
- ```
15150
-
15151
- </details>
15152
-
15153
15273
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toPairs)
15154
15274
 
15155
15275
  ### toString
@@ -17181,13 +17301,13 @@ describe('R.zipObj', () => {
17181
17301
  it('happy', () => {
17182
17302
  // this is wrong since 24.10.2020 `@types/ramda` changes
17183
17303
  const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])
17184
- result // $ExpectType { b: number; a: number; c: number; d: number; }
17304
+ ;[result.a, result.b, result.c, result.d] // $ExpectType number[]
17185
17305
  })
17186
17306
  it('imported from @types/ramda', () => {
17187
17307
  const result = zipObj(['a', 'b', 'c'], [1, 2, 3])
17188
17308
  const curriedResult = zipObj(['a', 'b', 'c'])([1, 2, 3])
17189
- result // $ExpectType { b: number; a: number; c: number; }
17190
- curriedResult // $ExpectType { b: number; a: number; c: number; }
17309
+ ;[result.a, result.b, result.c] // $ExpectType number[]
17310
+ ;[curriedResult.a, curriedResult.b, curriedResult.c] // $ExpectType number[]
17191
17311
  })
17192
17312
  })
17193
17313
  ```
@@ -17307,6 +17427,44 @@ describe('R.zipWith', () => {
17307
17427
 
17308
17428
  ## ❯ CHANGELOG
17309
17429
 
17430
+ 8.5.0
17431
+
17432
+ - Revert changes in `R.anyPass` introduced in `8.4.0` release. The reason is that the change was breaking the library older than `5.2.0` TypeScript.
17433
+
17434
+ - Wrong `R.partial` TS definition - [Issue #705](https://github.com/selfrefactor/rambda/issues/705)
17435
+
17436
+ - Add `R.dropRepeatsBy`
17437
+
17438
+ - Add `R.empty`
17439
+
17440
+ - Add `R.eqBy`
17441
+
17442
+ - Add `R.forEachObjIndexed`
17443
+
17444
+ 8.4.0
17445
+
17446
+ - Add `R.dissocPath`
17447
+
17448
+ - Fix TS definitions of `R.head/R.last` and add missing handle of empty string
17449
+
17450
+ - Add `R.removeIndex` - method was before only in `Rambdax`, but now since `R.dissocPath` is using it, it is added to main library.
17451
+
17452
+ - Allow `R.omit` to pass numbers as part of properties to omit, i.e. `R.omit(['a', 1], {a: {1: 1, 2: 2}})`
17453
+
17454
+ - R.keys always returns strings - [MR #700](https://github.com/selfrefactor/rambda/pull/700)
17455
+
17456
+ - Improve `R.prepend/R.append` type interference - [MR #699](https://github.com/selfrefactor/rambda/pull/699)
17457
+
17458
+ - Change `R.reduce` TS definitions so index is always received - [MR #696](https://github.com/selfrefactor/rambda/pull/696)
17459
+
17460
+ - Functions as a type guard in `R.anyPass` TS definitions - [MR #695](https://github.com/selfrefactor/rambda/pull/695)
17461
+
17462
+ - Fix R.append's curried type - [MR #694](https://github.com/selfrefactor/rambda/pull/694)
17463
+
17464
+ - Fix cannot compare errors in `Deno` with `R.equals` - [Issue #704](https://github.com/selfrefactor/rambda/issues/704).
17465
+
17466
+ - Fix cannot compare `BigInt` with `R.equals`
17467
+
17310
17468
  8.3.0
17311
17469
 
17312
17470
  Add the following methods:
@@ -17613,12 +17771,14 @@ Fix wrong versions in changelog
17613
17771
 
17614
17772
  ## ❯ Additional info
17615
17773
 
17616
- > Most influential contributors
17774
+ > Most influential contributors(in alphabetical order)
17617
17775
 
17618
17776
  - [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;
17619
17777
 
17620
17778
  - [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;
17621
17779
 
17780
+ - [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation
17781
+
17622
17782
  - [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;
17623
17783
 
17624
17784
  - [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;