rambda 8.3.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,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 | 🔳
@@ -786,7 +789,7 @@ describe('R.any', () => {
786
789
 
787
790
  ```typescript
788
791
 
789
- 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]
790
793
  ```
791
794
 
792
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`.
@@ -798,6 +801,7 @@ It accepts list of `predicates` and returns a function. This function with its `
798
801
  <summary>All TypeScript definitions</summary>
799
802
 
800
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];
801
805
  anyPass<T>(predicates: ((x: T) => boolean)[]): (input: T) => boolean;
802
806
  anyPass<T>(predicates: ((...inputs: T[]) => boolean)[]): (...inputs: T[]) => boolean;
803
807
  ```
@@ -925,6 +929,21 @@ describe('anyPass', () => {
925
929
  const filtered2 = xs.filter(pred)
926
930
  filtered2 // $ExpectType number[]
927
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
+ })
928
947
  })
929
948
  ```
930
949
 
@@ -1070,10 +1089,10 @@ test('happy', () => {
1070
1089
 
1071
1090
  ```typescript
1072
1091
 
1073
- append<T>(x: T, list: T[]): T[]
1092
+ append<T>(xToAppend: T, iterable: T[]): T[]
1074
1093
  ```
1075
1094
 
1076
- It adds element `x` at the end of `list`.
1095
+ It adds element `x` at the end of `iterable`.
1077
1096
 
1078
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>
1079
1098
 
@@ -1082,8 +1101,10 @@ It adds element `x` at the end of `list`.
1082
1101
  <summary>All TypeScript definitions</summary>
1083
1102
 
1084
1103
  ```typescript
1085
- append<T>(x: T, list: T[]): T[];
1086
- 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[];
1087
1108
  ```
1088
1109
 
1089
1110
  </details>
@@ -1114,7 +1135,8 @@ export function append(x, input){
1114
1135
  <summary><strong>Tests</strong></summary>
1115
1136
 
1116
1137
  ```javascript
1117
- import { append } from './append.js'
1138
+ // import { append } from './append.js'
1139
+ import { append } from 'ramda'
1118
1140
 
1119
1141
  test('happy', () => {
1120
1142
  expect(append('tests', [ 'write', 'more' ])).toEqual([
@@ -1140,20 +1162,62 @@ test('with strings', () => {
1140
1162
  <summary><strong>TypeScript</strong> test</summary>
1141
1163
 
1142
1164
  ```typescript
1143
- import {append} from 'rambda'
1165
+ import {append, prepend} from 'rambda'
1144
1166
 
1145
- const list = [1, 2, 3]
1167
+ const listOfNumbers = [1, 2, 3]
1168
+ const listOfNumbersAndStrings = [1, 'b', 3]
1146
1169
 
1147
- describe('R.append', () => {
1148
- it('happy', () => {
1149
- 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
+ })
1150
1180
 
1151
- 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
+ })
1152
1187
  })
1153
- it('curried', () => {
1154
- const result = append(4)(list)
1155
1188
 
1156
- 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
+ })
1157
1221
  })
1158
1222
  })
1159
1223
  ```
@@ -1745,21 +1809,17 @@ assocPath<Output>(path: Path): (newValue: any) => (obj: object) => Output;
1745
1809
 
1746
1810
  ```javascript
1747
1811
  import { cloneList } from './_internals/cloneList.js'
1812
+ import { createPath } from './_internals/createPath.js'
1748
1813
  import { isArray } from './_internals/isArray.js'
1749
- import { isInteger } from './_internals/isInteger.js'
1750
- import { assoc } from './assoc.js'
1814
+ import { isIndexInteger } from './_internals/isInteger.js'
1815
+ import { assocFn } from './assoc.js'
1751
1816
  import { curry } from './curry.js'
1752
1817
 
1753
- function assocPathFn(
1818
+ export function assocPathFn(
1754
1819
  path, newValue, input
1755
1820
  ){
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
- }
1821
+ const pathArrValue = createPath(path)
1822
+ if (pathArrValue.length === 0) return newValue
1763
1823
 
1764
1824
  const index = pathArrValue[ 0 ]
1765
1825
  if (pathArrValue.length > 1){
@@ -1769,7 +1829,7 @@ function assocPathFn(
1769
1829
  !input.hasOwnProperty(index)
1770
1830
 
1771
1831
  const nextInput = condition ?
1772
- isInteger(pathArrValue[ 1 ]) ?
1832
+ isIndexInteger(pathArrValue[ 1 ]) ?
1773
1833
  [] :
1774
1834
  {} :
1775
1835
  input[ index ]
@@ -1781,14 +1841,14 @@ function assocPathFn(
1781
1841
  )
1782
1842
  }
1783
1843
 
1784
- if (isInteger(index) && isArray(input)){
1844
+ if (isIndexInteger(index) && isArray(input)){
1785
1845
  const arr = cloneList(input)
1786
1846
  arr[ index ] = newValue
1787
1847
 
1788
1848
  return arr
1789
1849
  }
1790
1850
 
1791
- return assoc(
1851
+ return assocFn(
1792
1852
  index, newValue, input
1793
1853
  )
1794
1854
  }
@@ -1803,21 +1863,45 @@ export const assocPath = curry(assocPathFn)
1803
1863
  <summary><strong>Tests</strong></summary>
1804
1864
 
1805
1865
  ```javascript
1806
- 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
+ })
1807
1886
 
1808
1887
  test('string can be used as path input', () => {
1809
1888
  const testObj = {
1810
1889
  a : [ { b : 1 }, { b : 2 } ],
1811
1890
  d : 3,
1812
1891
  }
1813
- const result = assocPath(
1892
+ const result1 = assocPathFn(
1893
+ [ 'a', 0, 'b' ], 10, testObj
1894
+ )
1895
+ const result2 = assocPathFn(
1814
1896
  'a.0.b', 10, testObj
1815
1897
  )
1898
+
1816
1899
  const expected = {
1817
1900
  a : [ { b : 10 }, { b : 2 } ],
1818
1901
  d : 3,
1819
1902
  }
1820
- expect(result).toEqual(expected)
1903
+ expect(result1).toEqual(expected)
1904
+ expect(result2).toEqual(expected)
1821
1905
  })
1822
1906
 
1823
1907
  test('difference with ramda - doesn\'t overwrite primitive values with keys in the path', () => {
@@ -2987,6 +3071,10 @@ It returns a new object that does not contain property `prop`.
2987
3071
 
2988
3072
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissoc)
2989
3073
 
3074
+ ### dissocPath
3075
+
3076
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissocPath)
3077
+
2990
3078
  ### divide
2991
3079
 
2992
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>
@@ -3715,43 +3803,39 @@ import { isArray } from './_internals/isArray.js'
3715
3803
  import { type } from './type.js'
3716
3804
 
3717
3805
  export function _lastIndexOf(valueToFind, list){
3718
- if (!isArray(list)){
3806
+ if (!isArray(list))
3719
3807
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3720
- }
3808
+
3721
3809
  const typeOfValue = type(valueToFind)
3722
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3810
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3723
3811
  return list.lastIndexOf(valueToFind)
3724
3812
 
3725
3813
  const { length } = list
3726
3814
  let index = length
3727
3815
  let foundIndex = -1
3728
3816
 
3729
- while (--index > -1 && foundIndex === -1){
3730
- if (equals(list[ index ], valueToFind)){
3817
+ while (--index > -1 && foundIndex === -1)
3818
+ if (equals(list[ index ], valueToFind))
3731
3819
  foundIndex = index
3732
- }
3733
- }
3734
3820
 
3735
3821
  return foundIndex
3736
3822
  }
3737
3823
 
3738
3824
  export function _indexOf(valueToFind, list){
3739
- if (!isArray(list)){
3825
+ if (!isArray(list))
3740
3826
  throw new Error(`Cannot read property 'indexOf' of ${ list }`)
3741
- }
3827
+
3742
3828
  const typeOfValue = type(valueToFind)
3743
- if (![ 'Object', 'Array', 'NaN', 'RegExp' ].includes(typeOfValue))
3829
+ if (![ 'Array', 'NaN', 'Object', 'RegExp' ].includes(typeOfValue))
3744
3830
  return list.indexOf(valueToFind)
3745
3831
 
3746
3832
  let index = -1
3747
3833
  let foundIndex = -1
3748
3834
  const { length } = list
3749
3835
 
3750
- while (++index < length && foundIndex === -1){
3751
- if (equals(list[ index ], valueToFind)){
3836
+ while (++index < length && foundIndex === -1)
3837
+ if (equals(list[ index ], valueToFind))
3752
3838
  foundIndex = index
3753
- }
3754
- }
3755
3839
 
3756
3840
  return foundIndex
3757
3841
  }
@@ -3759,17 +3843,16 @@ export function _indexOf(valueToFind, list){
3759
3843
  function _arrayFromIterator(iter){
3760
3844
  const list = []
3761
3845
  let next
3762
- while (!(next = iter.next()).done){
3846
+ while (!(next = iter.next()).done)
3763
3847
  list.push(next.value)
3764
- }
3765
3848
 
3766
3849
  return list
3767
3850
  }
3768
3851
 
3769
- function _equalsSets(a, b){
3770
- if (a.size !== b.size){
3852
+ function _compareSets(a, b){
3853
+ if (a.size !== b.size)
3771
3854
  return false
3772
- }
3855
+
3773
3856
  const aList = _arrayFromIterator(a.values())
3774
3857
  const bList = _arrayFromIterator(b.values())
3775
3858
 
@@ -3778,11 +3861,11 @@ function _equalsSets(a, b){
3778
3861
  return filtered.length === 0
3779
3862
  }
3780
3863
 
3781
- function parseError(maybeError){
3782
- const typeofError = maybeError.__proto__.toString()
3783
- 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
3784
3867
 
3785
- return [ typeofError, maybeError.message ]
3868
+ return a.toString() === b.toString()
3786
3869
  }
3787
3870
 
3788
3871
  function parseDate(maybeDate){
@@ -3803,40 +3886,36 @@ export function equals(a, b){
3803
3886
  const aType = type(a)
3804
3887
 
3805
3888
  if (aType !== type(b)) return false
3806
- if (aType === 'Function'){
3889
+ if (aType === 'Function')
3807
3890
  return a.name === undefined ? false : a.name === b.name
3808
- }
3809
3891
 
3810
- if ([ 'NaN', 'Undefined', 'Null' ].includes(aType)) return true
3892
+ if ([ 'NaN', 'Null', 'Undefined' ].includes(aType)) return true
3811
3893
 
3812
- if (aType === 'Number'){
3894
+ if ([ 'BigInt', 'Number' ].includes(aType)){
3813
3895
  if (Object.is(-0, a) !== Object.is(-0, b)) return false
3814
3896
 
3815
3897
  return a.toString() === b.toString()
3816
3898
  }
3817
3899
 
3818
- if ([ 'String', 'Boolean' ].includes(aType)){
3900
+ if ([ 'Boolean', 'String' ].includes(aType))
3819
3901
  return a.toString() === b.toString()
3820
- }
3821
3902
 
3822
3903
  if (aType === 'Array'){
3823
3904
  const aClone = Array.from(a)
3824
3905
  const bClone = Array.from(b)
3825
3906
 
3826
- if (aClone.toString() !== bClone.toString()){
3907
+ if (aClone.toString() !== bClone.toString())
3827
3908
  return false
3828
- }
3829
3909
 
3830
3910
  let loopArrayFlag = true
3831
3911
  aClone.forEach((aCloneInstance, aCloneIndex) => {
3832
- if (loopArrayFlag){
3912
+ if (loopArrayFlag)
3833
3913
  if (
3834
3914
  aCloneInstance !== bClone[ aCloneIndex ] &&
3835
3915
  !equals(aCloneInstance, bClone[ aCloneIndex ])
3836
- ){
3916
+ )
3837
3917
  loopArrayFlag = false
3838
- }
3839
- }
3918
+
3840
3919
  })
3841
3920
 
3842
3921
  return loopArrayFlag
@@ -3845,34 +3924,31 @@ export function equals(a, b){
3845
3924
  const aRegex = parseRegex(a)
3846
3925
  const bRegex = parseRegex(b)
3847
3926
 
3848
- if (aRegex[ 0 ]){
3927
+ if (aRegex[ 0 ])
3849
3928
  return bRegex[ 0 ] ? aRegex[ 1 ] === bRegex[ 1 ] : false
3850
- } else if (bRegex[ 0 ]) return false
3929
+ else if (bRegex[ 0 ]) return false
3851
3930
 
3852
3931
  const aDate = parseDate(a)
3853
3932
  const bDate = parseDate(b)
3854
3933
 
3855
- if (aDate[ 0 ]){
3934
+ if (aDate[ 0 ])
3856
3935
  return bDate[ 0 ] ? aDate[ 1 ] === bDate[ 1 ] : false
3857
- } else if (bDate[ 0 ]) return false
3936
+ else if (bDate[ 0 ]) return false
3858
3937
 
3859
- const aError = parseError(a)
3860
- const bError = parseError(b)
3938
+ if (a instanceof Error){
3939
+ if (!(b instanceof Error)) return false
3861
3940
 
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)
3941
+ return compareErrors(a, b)
3869
3942
  }
3943
+
3944
+ if (aType === 'Set')
3945
+ return _compareSets(a, b)
3946
+
3870
3947
  if (aType === 'Object'){
3871
3948
  const aKeys = Object.keys(a)
3872
3949
 
3873
- if (aKeys.length !== Object.keys(b).length){
3950
+ if (aKeys.length !== Object.keys(b).length)
3874
3951
  return false
3875
- }
3876
3952
 
3877
3953
  let loopObjectFlag = true
3878
3954
  aKeys.forEach(aKeyInstance => {
@@ -3880,9 +3956,9 @@ export function equals(a, b){
3880
3956
  const aValue = a[ aKeyInstance ]
3881
3957
  const bValue = b[ aKeyInstance ]
3882
3958
 
3883
- if (aValue !== bValue && !equals(aValue, bValue)){
3959
+ if (aValue !== bValue && !equals(aValue, bValue))
3884
3960
  loopObjectFlag = false
3885
- }
3961
+
3886
3962
  }
3887
3963
  })
3888
3964
 
@@ -3969,6 +4045,7 @@ test('new Error', () => {
3969
4045
  expect(equals(new Error('XXX'), new Error('YYY'))).toBeFalse()
3970
4046
  expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3971
4047
  expect(equals(new Error('XXX'), new TypeError('YYY'))).toBeFalse()
4048
+ expect(equals(new Error('XXX'), new Error('XXX'))).toBeTrue()
3972
4049
  })
3973
4050
 
3974
4051
  test('with dates', () => {
@@ -3997,8 +4074,8 @@ test('ramda spec', () => {
3997
4074
  b : 3,
3998
4075
  },
3999
4076
  {
4000
- b : 3,
4001
4077
  a : 2,
4078
+ b : 3,
4002
4079
  })).toBeTrue()
4003
4080
 
4004
4081
  expect(equals({
@@ -4094,8 +4171,8 @@ test('various examples', () => {
4094
4171
  b : 2,
4095
4172
  },
4096
4173
  {
4097
- b : 2,
4098
4174
  a : 1,
4175
+ b : 2,
4099
4176
  })).toBeTrue()
4100
4177
 
4101
4178
  expect(equals({
@@ -4121,8 +4198,8 @@ test('various examples', () => {
4121
4198
  b : 2,
4122
4199
  },
4123
4200
  {
4124
- b : 2,
4125
4201
  a : 1,
4202
+ b : 2,
4126
4203
  c : 3,
4127
4204
  })).toBeFalse()
4128
4205
 
@@ -4134,8 +4211,8 @@ test('various examples', () => {
4134
4211
  },
4135
4212
  {
4136
4213
  x : {
4137
- b : 2,
4138
4214
  a : 1,
4215
+ b : 2,
4139
4216
  c : 3,
4140
4217
  },
4141
4218
  })).toBeFalse()
@@ -4145,8 +4222,8 @@ test('various examples', () => {
4145
4222
  b : 2,
4146
4223
  },
4147
4224
  {
4148
- b : 3,
4149
4225
  a : 1,
4226
+ b : 3,
4150
4227
  })).toBeFalse()
4151
4228
 
4152
4229
  expect(equals({ a : { b : { c : 1 } } }, { a : { b : { c : 1 } } })).toBeTrue()
@@ -4195,26 +4272,32 @@ test('with negative zero', () => {
4195
4272
  expect(equals(-0, 1)).toBeFalse()
4196
4273
  })
4197
4274
 
4198
- 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
+ })
4199
4282
 
4200
4283
  describe('brute force', () => {
4201
4284
  compareCombinations({
4202
- fn : equals,
4203
- fnRamda : equalsRamda,
4204
- firstInput : possibleInputs,
4205
- secondInput : possibleInputs,
4206
- callback : errorsCounters => {
4285
+ callback : errorsCounters => {
4207
4286
  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
- `)
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
+ `)
4217
4296
  },
4297
+ firstInput : variousTypes,
4298
+ fn : equals,
4299
+ fnRamda : equalsRamda,
4300
+ secondInput : variousTypes,
4218
4301
  })
4219
4302
  })
4220
4303
  ```
@@ -5716,7 +5799,7 @@ describe('R.hasPath', () => {
5716
5799
 
5717
5800
  ```typescript
5718
5801
 
5719
- head(input: string): string
5802
+ head(str: string): string
5720
5803
  ```
5721
5804
 
5722
5805
  It returns the first element of list or string `input`.
@@ -5728,8 +5811,10 @@ It returns the first element of list or string `input`.
5728
5811
  <summary>All TypeScript definitions</summary>
5729
5812
 
5730
5813
  ```typescript
5731
- head(input: string): string;
5732
- 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>
5733
5818
  head<T extends readonly unknown[]>(array: T): FirstArrayElement<T>
5734
5819
  ```
5735
5820
 
@@ -5771,34 +5856,46 @@ test('head', () => {
5771
5856
  <summary><strong>TypeScript</strong> test</summary>
5772
5857
 
5773
5858
  ```typescript
5774
- import {mixedList, mixedListConst} from '_internals/typescriptTestUtils'
5775
- 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'
5776
5869
 
5777
5870
  describe('R.head', () => {
5778
5871
  it('string', () => {
5779
- const result = head('foo')
5780
- result // $ExpectType string
5872
+ head(string) // $ExpectType string
5873
+ last(string) // $ExpectType string
5781
5874
  })
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
5875
+ it('empty string', () => {
5876
+ head(emptyString) // $ExpectType undefined
5877
+ last(emptyString) // $ExpectType undefined
5789
5878
  })
5790
- it('mixed const', () => {
5791
- const result = head(mixedListConst)
5792
- 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
5793
5885
  })
5794
- it('empty array - case 1', () => {
5795
- const result = head([])
5796
- 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
5797
5892
  })
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
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"
5802
5899
  })
5803
5900
  })
5804
5901
  ```
@@ -6693,7 +6790,7 @@ describe('R.juxt', () => {
6693
6790
 
6694
6791
  ```typescript
6695
6792
 
6696
- keys<T extends object>(x: T): (keyof T)[]
6793
+ keys<T extends object>(x: T): (keyof T & string)[]
6697
6794
  ```
6698
6795
 
6699
6796
  It applies `Object.keys` over `x` and returns its keys.
@@ -6705,7 +6802,7 @@ It applies `Object.keys` over `x` and returns its keys.
6705
6802
  <summary>All TypeScript definitions</summary>
6706
6803
 
6707
6804
  ```typescript
6708
- keys<T extends object>(x: T): (keyof T)[];
6805
+ keys<T extends object>(x: T): (keyof T & string)[];
6709
6806
  keys<T>(x: T): string[];
6710
6807
  ```
6711
6808
 
@@ -6737,32 +6834,13 @@ test('happy', () => {
6737
6834
 
6738
6835
  </details>
6739
6836
 
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
6837
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#keys)
6760
6838
 
6761
6839
  ### last
6762
6840
 
6763
6841
  ```typescript
6764
6842
 
6765
- last(input: string): string
6843
+ last(str: ''): undefined
6766
6844
  ```
6767
6845
 
6768
6846
  It returns the last element of `input`, as the `input` can be either a string or an array.
@@ -6774,8 +6852,10 @@ It returns the last element of `input`, as the `input` can be either a string or
6774
6852
  <summary>All TypeScript definitions</summary>
6775
6853
 
6776
6854
  ```typescript
6777
- last(input: string): string;
6778
- 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>
6779
6859
  last<T extends readonly unknown[]>(array: T): LastArrayElement<T>
6780
6860
  ```
6781
6861
 
@@ -6817,45 +6897,6 @@ test('with string', () => {
6817
6897
 
6818
6898
  </details>
6819
6899
 
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
6900
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#last)
6860
6901
 
6861
6902
  ### lastIndexOf
@@ -9634,22 +9675,20 @@ omit<T>(propsToOmit: string): (obj: object) => T;
9634
9675
 
9635
9676
  ```javascript
9636
9677
  import { createPath } from './_internals/createPath.js'
9678
+ import { includes } from './_internals/includes.js'
9637
9679
 
9638
9680
  export function omit(propsToOmit, obj){
9639
9681
  if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)
9640
9682
 
9641
- if (obj === null || obj === undefined){
9683
+ if (obj === null || obj === undefined)
9642
9684
  return undefined
9643
- }
9644
9685
 
9645
9686
  const propsToOmitValue = createPath(propsToOmit, ',')
9646
9687
  const willReturn = {}
9647
9688
 
9648
- for (const key in obj){
9649
- if (!propsToOmitValue.includes(key)){
9689
+ for (const key in obj)
9690
+ if (!includes(key, propsToOmitValue))
9650
9691
  willReturn[ key ] = obj[ key ]
9651
- }
9652
- }
9653
9692
 
9654
9693
  return willReturn
9655
9694
  }
@@ -9678,18 +9717,17 @@ test('with string as condition', () => {
9678
9717
  expect(resultCurry).toEqual(expectedResult)
9679
9718
  })
9680
9719
 
9681
- test('with null', () => {
9682
- 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 })
9683
9727
  })
9684
9728
 
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
- })
9729
+ test('with null', () => {
9730
+ expect(omit('a,b', null)).toBeUndefined()
9693
9731
  })
9694
9732
 
9695
9733
  test('happy', () => {
@@ -10035,7 +10073,18 @@ test('index lens', () => {
10035
10073
 
10036
10074
  ```typescript
10037
10075
 
10038
- 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
10039
10088
  ```
10040
10089
 
10041
10090
  It is very similar to `R.curry`, but you can pass initial arguments when you create the curried function.
@@ -10050,13 +10099,31 @@ The name comes from the fact that you partially inject the inputs.
10050
10099
  <summary>All TypeScript definitions</summary>
10051
10100
 
10052
10101
  ```typescript
10053
- partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T;
10054
- partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0, V1]): (x2: V2) => T;
10055
- 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;
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;
10060
10127
  ```
10061
10128
 
10062
10129
  </details>
@@ -10066,15 +10133,21 @@ partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
10066
10133
  <summary><strong>R.partial</strong> source</summary>
10067
10134
 
10068
10135
  ```javascript
10136
+ import { isArray } from './_internals/isArray.js'
10137
+
10069
10138
  export function partial(fn, ...args){
10070
10139
  const len = fn.length
10071
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
+
10072
10145
  return (...rest) => {
10073
- if (args.length + rest.length >= len){
10074
- return fn(...args, ...rest)
10146
+ if (argList.length + rest.length >= len){
10147
+ return fn(...argList, ...rest)
10075
10148
  }
10076
10149
 
10077
- return partial(fn, ...[ ...args, ...rest ])
10150
+ return partial(fn, ...[ ...argList, ...rest ])
10078
10151
  }
10079
10152
  }
10080
10153
  ```
@@ -10092,7 +10165,7 @@ import { type } from './type.js'
10092
10165
  const greet = (
10093
10166
  salutation, title, firstName, lastName
10094
10167
  ) =>
10095
- salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!'
10168
+ [salutation, title, firstName, lastName]
10096
10169
 
10097
10170
  test('happy', () => {
10098
10171
  const canPassAnyNumberOfArguments = partial(
@@ -10104,8 +10177,8 @@ test('happy', () => {
10104
10177
 
10105
10178
  expect(type(fn)).toBe('Function')
10106
10179
 
10107
- expect(fn('bar')).toBe('Hello, Ms. foo bar!')
10108
- 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'])
10109
10182
  })
10110
10183
 
10111
10184
  test('extra arguments are ignored', () => {
@@ -10118,7 +10191,7 @@ test('extra arguments are ignored', () => {
10118
10191
 
10119
10192
  expect(fn(
10120
10193
  'bar', 1, 2
10121
- )).toBe('Hello, Ms. foo bar!')
10194
+ )).toStrictEqual(['Hello', 'Ms.', 'foo', 'bar'])
10122
10195
  })
10123
10196
 
10124
10197
  test('when array is input', () => {
@@ -10146,7 +10219,7 @@ test('ramda spec', () => {
10146
10219
  const sayHello = partial(greet, 'Hello')
10147
10220
  const sayHelloToMs = partial(sayHello, 'Ms.')
10148
10221
 
10149
- expect(sayHelloToMs('Jane', 'Jones')).toBe('Hello, Ms. Jane Jones!')
10222
+ expect(sayHelloToMs('Jane', 'Jones')).toStrictEqual(['Hello', 'Ms.', 'Jane', 'Jones'])
10150
10223
  })
10151
10224
  ```
10152
10225
 
@@ -10161,21 +10234,50 @@ import {partial} from 'rambda'
10161
10234
 
10162
10235
  describe('R.partial', () => {
10163
10236
  it('happy', () => {
10164
- function greet(
10165
- salutation: string,
10166
- title: string,
10167
- firstName: string,
10168
- lastName: string
10237
+ function fn(
10238
+ aString: string,
10239
+ aNumber: number,
10240
+ aBoolean: boolean,
10241
+ aNull: null
10169
10242
  ) {
10170
- return `${salutation}, ${title} ${firstName} ${lastName}!`
10243
+ return { aString, aNumber, aBoolean, aNull }
10171
10244
  }
10172
10245
 
10173
- const sayHello = partial(greet, ['Hello'])
10174
- const sayHelloToMs = partial(sayHello, ['Ms.'])
10175
- const result = sayHelloToMs('Jane', 'Jones')
10176
- 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; }
10177
10257
  })
10178
- })
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
+ })})
10179
10281
  ```
10180
10282
 
10181
10283
  </details>
@@ -11318,10 +11420,10 @@ test('works with list as input and number as props - props to pick is a string',
11318
11420
  test('with symbol', () => {
11319
11421
  const symbolProp = Symbol('s')
11320
11422
  expect(pick([ symbolProp ], { [ symbolProp ] : 'a' })).toMatchInlineSnapshot(`
11321
- {
11322
- Symbol(s): "a",
11323
- }
11324
- `)
11423
+ {
11424
+ Symbol(s): "a",
11425
+ }
11426
+ `)
11325
11427
  })
11326
11428
  ```
11327
11429
 
@@ -11674,7 +11776,7 @@ describe('R.pluck', () => {
11674
11776
 
11675
11777
  ```typescript
11676
11778
 
11677
- prepend<T>(x: T, input: T[]): T[]
11779
+ prepend<T>(xToPrepend: T, iterable: T[]): T[]
11678
11780
  ```
11679
11781
 
11680
11782
  It adds element `x` at the beginning of `list`.
@@ -11686,8 +11788,10 @@ It adds element `x` at the beginning of `list`.
11686
11788
  <summary>All TypeScript definitions</summary>
11687
11789
 
11688
11790
  ```typescript
11689
- prepend<T>(x: T, input: T[]): T[];
11690
- 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[];
11691
11795
  ```
11692
11796
 
11693
11797
  </details>
@@ -11735,31 +11839,6 @@ test('with string instead of array', () => {
11735
11839
 
11736
11840
  </details>
11737
11841
 
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
11842
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prepend)
11764
11843
 
11765
11844
  ### product
@@ -12721,6 +12800,96 @@ describe('R.reject with objects', () => {
12721
12800
 
12722
12801
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reject)
12723
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
+
12724
12893
  ### repeat
12725
12894
 
12726
12895
  ```typescript
@@ -15126,30 +15295,6 @@ test('happy', () => {
15126
15295
 
15127
15296
  </details>
15128
15297
 
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
15298
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toPairs)
15154
15299
 
15155
15300
  ### toString
@@ -17181,13 +17326,13 @@ describe('R.zipObj', () => {
17181
17326
  it('happy', () => {
17182
17327
  // this is wrong since 24.10.2020 `@types/ramda` changes
17183
17328
  const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])
17184
- result // $ExpectType { b: number; a: number; c: number; d: number; }
17329
+ ;[result.a, result.b, result.c, result.d] // $ExpectType number[]
17185
17330
  })
17186
17331
  it('imported from @types/ramda', () => {
17187
17332
  const result = zipObj(['a', 'b', 'c'], [1, 2, 3])
17188
17333
  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; }
17334
+ ;[result.a, result.b, result.c] // $ExpectType number[]
17335
+ ;[curriedResult.a, curriedResult.b, curriedResult.c] // $ExpectType number[]
17191
17336
  })
17192
17337
  })
17193
17338
  ```
@@ -17307,6 +17452,30 @@ describe('R.zipWith', () => {
17307
17452
 
17308
17453
  ## ❯ CHANGELOG
17309
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
+
17310
17479
  8.3.0
17311
17480
 
17312
17481
  Add the following methods:
@@ -17613,12 +17782,14 @@ Fix wrong versions in changelog
17613
17782
 
17614
17783
  ## ❯ Additional info
17615
17784
 
17616
- > Most influential contributors
17785
+ > Most influential contributors(in alphabetical order)
17617
17786
 
17618
17787
  - [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;
17619
17788
 
17620
17789
  - [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;
17621
17790
 
17791
+ - [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation
17792
+
17622
17793
  - [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;
17623
17794
 
17624
17795
  - [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;