rambda 9.2.1 → 9.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/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ 9.4.0
2
+
3
+ - Fix `deno` release
4
+
5
+ - Fix too strict `true` condition in `R.ifElse` - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)
6
+
7
+ - Change `R.groupBy` typings to match `@types/ramda` typings
8
+
9
+ 9.3.0
10
+
11
+ - Breaking change in relation to TS typings of `R.assoc`, `R.dissoc` and `R.modify` - https://github.com/ramda/types/pull/37
12
+
13
+ - Add `R.isNotEmpty` as it is new method in `Ramda`
14
+
15
+ - Fix `R.head`/`R.last` TS definition - It returns `undefined` if array has length of 0. Before
16
+
1
17
  9.2.1
2
18
 
3
19
  - Broken `Deno` build - [Issue #731](https://github.com/selfrefactor/rambda/issues/731)
package/README.md CHANGED
@@ -2,14 +2,12 @@
2
2
 
3
3
  `Rambda` is smaller and faster alternative to the popular functional programming library **Ramda**. - [Documentation](https://selfrefactor.github.io/rambda/#/)
4
4
 
5
- [![CircleCI](https://circleci.com/gh/selfrefactor/rambda/tree/master.svg?style=svg)](https://circleci.com/gh/selfrefactor/rambda/tree/master)
6
5
  [![codecov](https://codecov.io/gh/selfrefactor/rambda/branch/master/graph/badge.svg)](https://codecov.io/gh/selfrefactor/rambda)
7
6
  ![Commit activity](https://img.shields.io/github/commit-activity/y/selfrefactor/rambda)
8
- ![All contributors](https://img.shields.io/github/contributors/selfrefactor/rambda)
9
7
  ![Library size](https://img.shields.io/bundlephobia/minzip/rambda)
10
8
  [![install size](https://packagephobia.com/badge?p=rambda)](https://packagephobia.com/result?p=rambda)
11
- [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/rambda)
12
9
  [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](https://github.com/selfrefactor/rambda/pulls)
10
+ [![GitHub contributors](https://img.shields.io/github/contributors/selfrefactor/rambda.svg)](https://github.com/selfrefactor/rambda/graphs/contributors)
13
11
 
14
12
  ## ❯ Example use
15
13
 
@@ -106,59 +104,57 @@ One of the main issues with `Ramda` is the slow process of releasing new version
106
104
 
107
105
  <details>
108
106
  <summary>
109
- Click to see the full list of 43 Ramda methods not implemented in Rambda and their status.
107
+ Click to see the full list of 46 Ramda methods not implemented in Rambda and their status.
110
108
  </summary>
111
109
 
112
- - into
113
- - invert
110
+ - construct - Using classes is not very functional programming oriented.
111
+ - constructN - same as above
112
+ - into - no support for transducer as it is overly complex to implement, understand and read.
113
+ - invert - overly complicated and limited use case
114
114
  - invertObj
115
115
  - invoker
116
- - keysIn
116
+ - keysIn - we shouldn't encourage extending object with `.prototype`
117
117
  - lift
118
118
  - liftN
119
- - mapAccum
119
+ - mapAccum - `Ramda` example doesn't looks convincing
120
120
  - mapAccumRight
121
- - memoizeWith
122
- - mergeDeepWith
121
+ - memoizeWith - hard to imagine its usage in context of `R.pipe`/`R.compose`
122
+ - mergeDeepWith - limited use case
123
123
  - mergeDeepWithKey
124
124
  - mergeWithKey
125
- - nAry
126
- - nthArg
127
- - o
128
- - otherwise
129
- - pair
130
- - partialRight
131
- - pathSatisfies
125
+ - nAry - hard to argument about and hard to create meaningful TypeScript definitions
126
+ - nthArg - limited use case
127
+ - o - enough TypeScript issues with `R.pipe`/`R.compose` to add more composition methods
128
+ - otherwise - naming is confusing
129
+ - pair - `left-pad` types of debacles happens partially because of such methods that should not be hidden, bur rather part of your code base even if they need to exist.
130
+ - partialRight - I dislike `R.partial`, so I don't want to add more methods that are based on it
132
131
  - pipeWith
133
- - project
132
+ - project - naming is confusing, but also limited use case
134
133
  - promap
135
- - reduceRight
136
- - reduceWhile
134
+ - reduceRight - I find `right/left` methods confusing so I added them only where it makes sense.
135
+ - reduceWhile - functions with 4 inputs - I think that even 3 is too much
137
136
  - reduced
138
- - remove
139
- - scan
137
+ - remove - nice name but it is too generic. Also, `Rambdax` has such method and there it works very differently
138
+ - scan - hard to explain
140
139
  - sequence
141
140
  - splitWhenever
142
141
  - symmetricDifferenceWith
143
142
  - andThen
144
143
  - toPairsIn
144
+ - transduce - currently is out of focus
145
+ - traverse - same as above
145
146
  - unary
146
147
  - uncurryN
147
- - unfold
148
- - unionWith
148
+ - unfold - similar to `R.scan` and I find that it doesn't help with readability
149
+ - unionWith - why it has its usage, I want to limit number of methods that accept more than 2 arguments
149
150
  - until
150
- - useWith
151
+ - useWith - hard to explain
151
152
  - valuesIn
152
- - xprod
153
+ - xprod - limited use case
153
154
  - thunkify
154
- - default
155
-
156
- Most of above methods are in progress to be added to **Rambda**. The following methods are not going to be added:
157
155
  - __ - 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.
158
- - construct - Using classes is not very functional programming oriented.
159
- - constructN - same as above
160
- - transduce - currently is out of focus
161
- - traverse - same as above
156
+
157
+ The following methods are not going to be added(reason for exclusion is provided as a comment):
162
158
  </details>
163
159
 
164
160
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-missing-ramda-methods)
@@ -216,7 +212,7 @@ There are methods which are benchmarked only with `Ramda` and `Rambda`(i.e. no `
216
212
 
217
213
  Note that some of these methods, are called with and without curring. This is done in order to give more detailed performance feedback.
218
214
 
219
- The benchmarks results are produced from latest versions of *Rambda*, *Lodash*(4.17.21) and *Ramda*(0.30.0).
215
+ The benchmarks results are produced from latest versions of *Rambda*, *Lodash*(4.17.21) and *Ramda*(0.30.1).
220
216
 
221
217
  </summary>
222
218
 
@@ -1772,7 +1768,7 @@ describe('applySpec', () => {
1772
1768
 
1773
1769
  ### ascend
1774
1770
 
1775
- <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20R.sort(%0A%20%20R.ascend(x%20%3D%3E%20x)%2C%0A%20%20%5B2%2C%201%5D%0A)%0A%2F%2F%20%3D%3E%20%5B1%2C%202%5D">Try this <strong>R.ascend</strong> example in Rambda REPL</a>
1771
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20R.sort(R.descend(x%20%3D%3E%20x)%2C%20%5B2%2C%201%5D)%0A%2F%2F%20%3D%3E%20%5B1%2C%202%5D">Try this <strong>R.ascend</strong> example in Rambda REPL</a>
1776
1772
 
1777
1773
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#ascend)
1778
1774
 
@@ -1869,7 +1865,7 @@ export const assocPath = curry(assocPathFn)
1869
1865
  ```javascript
1870
1866
  import { assocPathFn } from './assocPath.js'
1871
1867
 
1872
- test.only('happy', () => {
1868
+ test('happy', () => {
1873
1869
  const path = 'a.c.1'
1874
1870
  const input = {
1875
1871
  a : {
@@ -1910,7 +1906,7 @@ test('string can be used as path input', () => {
1910
1906
 
1911
1907
  test('difference with ramda - doesn\'t overwrite primitive values with keys in the path', () => {
1912
1908
  const obj = { a : 'str' }
1913
- const result = assocPath(
1909
+ const result = assocPathFn(
1914
1910
  [ 'a', 'b' ], 42, obj
1915
1911
  )
1916
1912
 
@@ -1924,35 +1920,35 @@ test('difference with ramda - doesn\'t overwrite primitive values with keys in t
1924
1920
  })
1925
1921
  })
1926
1922
 
1927
- test('bug', () => {
1923
+ test('bug 524', () => {
1928
1924
  /*
1929
1925
  https://github.com/selfrefactor/rambda/issues/524
1930
1926
  */
1931
1927
  const state = {}
1932
1928
 
1933
- const withDateLike = assocPath(
1929
+ const withDateLike = assocPathFn(
1934
1930
  [ 'outerProp', '2020-03-10' ],
1935
1931
  { prop : 2 },
1936
1932
  state
1937
1933
  )
1938
- const withNumber = assocPath(
1939
- [ 'outerProp', '5' ], { prop : 2 }, state
1934
+ const withNumber = assocPathFn(
1935
+ [ 'outerProp,5' ], { prop : 2 }, state
1940
1936
  )
1941
1937
 
1942
1938
  const withDateLikeExpected = { outerProp : { '2020-03-10' : { prop : 2 } } }
1943
1939
  const withNumberExpected = { outerProp : { 5 : { prop : 2 } } }
1944
1940
  expect(withDateLike).toEqual(withDateLikeExpected)
1945
- expect(withNumber).toEqual(withNumberExpected)
1941
+ // expect(withNumber).toEqual(withNumberExpected)
1946
1942
  })
1947
1943
 
1948
1944
  test('adds a key to an empty object', () => {
1949
- expect(assocPath(
1945
+ expect(assocPathFn(
1950
1946
  [ 'a' ], 1, {}
1951
1947
  )).toEqual({ a : 1 })
1952
1948
  })
1953
1949
 
1954
1950
  test('adds a key to a non-empty object', () => {
1955
- expect(assocPath(
1951
+ expect(assocPathFn(
1956
1952
  'b', 2, { a : 1 }
1957
1953
  )).toEqual({
1958
1954
  a : 1,
@@ -1961,7 +1957,7 @@ test('adds a key to a non-empty object', () => {
1961
1957
  })
1962
1958
 
1963
1959
  test('adds a nested key to a non-empty object', () => {
1964
- expect(assocPath(
1960
+ expect(assocPathFn(
1965
1961
  'b.c', 2, { a : 1 }
1966
1962
  )).toEqual({
1967
1963
  a : 1,
@@ -1969,9 +1965,9 @@ test('adds a nested key to a non-empty object', () => {
1969
1965
  })
1970
1966
  })
1971
1967
 
1972
- test('adds a nested key to a nested non-empty object - curry case 1', () => {
1973
- expect(assocPath('b.d',
1974
- 3)({
1968
+ test('adds a nested key to a nested non-empty object', () => {
1969
+ expect(assocPathFn('b.d',
1970
+ 3,{
1975
1971
  a : 1,
1976
1972
  b : { c : 2 },
1977
1973
  })).toEqual({
@@ -1983,74 +1979,58 @@ test('adds a nested key to a nested non-empty object - curry case 1', () => {
1983
1979
  })
1984
1980
  })
1985
1981
 
1986
- test('adds a key to a non-empty object - curry case 1', () => {
1987
- expect(assocPath('b', 2)({ a : 1 })).toEqual({
1982
+ test('adds a key to a non-empty object', () => {
1983
+ expect(assocPathFn('b', 2, { a : 1 })).toEqual({
1988
1984
  a : 1,
1989
1985
  b : 2,
1990
1986
  })
1991
1987
  })
1992
1988
 
1993
- test('adds a nested key to a non-empty object - curry case 1', () => {
1994
- expect(assocPath('b.c', 2)({ a : 1 })).toEqual({
1989
+ test('adds a nested key to a non-empty object', () => {
1990
+ expect(assocPathFn('b.c', 2, { a : 1 })).toEqual({
1995
1991
  a : 1,
1996
1992
  b : { c : 2 },
1997
1993
  })
1998
1994
  })
1999
1995
 
2000
- test('adds a key to a non-empty object - curry case 2', () => {
2001
- expect(assocPath('b')(2, { a : 1 })).toEqual({
2002
- a : 1,
2003
- b : 2,
2004
- })
2005
- })
2006
-
2007
- test('adds a key to a non-empty object - curry case 3', () => {
2008
- const result = assocPath('b')(2)({ a : 1 })
2009
-
2010
- expect(result).toEqual({
2011
- a : 1,
2012
- b : 2,
2013
- })
2014
- })
2015
-
2016
1996
  test('changes an existing key', () => {
2017
- expect(assocPath(
1997
+ expect(assocPathFn(
2018
1998
  'a', 2, { a : 1 }
2019
1999
  )).toEqual({ a : 2 })
2020
2000
  })
2021
2001
 
2022
2002
  test('undefined is considered an empty object', () => {
2023
- expect(assocPath(
2003
+ expect(assocPathFn(
2024
2004
  'a', 1, undefined
2025
2005
  )).toEqual({ a : 1 })
2026
2006
  })
2027
2007
 
2028
2008
  test('null is considered an empty object', () => {
2029
- expect(assocPath(
2009
+ expect(assocPathFn(
2030
2010
  'a', 1, null
2031
2011
  )).toEqual({ a : 1 })
2032
2012
  })
2033
2013
 
2034
2014
  test('value can be null', () => {
2035
- expect(assocPath(
2015
+ expect(assocPathFn(
2036
2016
  'a', null, null
2037
2017
  )).toEqual({ a : null })
2038
2018
  })
2039
2019
 
2040
2020
  test('value can be undefined', () => {
2041
- expect(assocPath(
2021
+ expect(assocPathFn(
2042
2022
  'a', undefined, null
2043
2023
  )).toEqual({ a : undefined })
2044
2024
  })
2045
2025
 
2046
2026
  test('assignment is shallow', () => {
2047
- expect(assocPath(
2027
+ expect(assocPathFn(
2048
2028
  'a', { b : 2 }, { a : { c : 3 } }
2049
2029
  )).toEqual({ a : { b : 2 } })
2050
2030
  })
2051
2031
 
2052
2032
  test('empty array as path', () => {
2053
- const result = assocPath(
2033
+ const result = assocPathFn(
2054
2034
  [], 3, {
2055
2035
  a : 1,
2056
2036
  b : 2,
@@ -2061,7 +2041,7 @@ test('empty array as path', () => {
2061
2041
 
2062
2042
  test('happy', () => {
2063
2043
  const expected = { foo : { bar : { baz : 42 } } }
2064
- const result = assocPath(
2044
+ const result = assocPathFn(
2065
2045
  [ 'foo', 'bar', 'baz' ], 42, { foo : null }
2066
2046
  )
2067
2047
  expect(result).toEqual(expected)
@@ -2888,7 +2868,7 @@ describe('R.defaultTo with Ramda spec', () => {
2888
2868
 
2889
2869
  ### descend
2890
2870
 
2891
- <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?R.sort(%0A%20%20R.descend(x%20%3D%3E%20x)%2C%0A%20%20%5B1%2C%202%5D%0Aconst%20result%20%3D%20)%0A%2F%2F%20%3D%3E%20%5B2%2C%201%5D">Try this <strong>R.descend</strong> example in Rambda REPL</a>
2871
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20R.sort(R.descend(x%20%3D%3E%20x)%2C%20%5B1%2C%202%5D)%0A%2F%2F%20%3D%3E%20%5B2%2C%201%5D">Try this <strong>R.descend</strong> example in Rambda REPL</a>
2892
2872
 
2893
2873
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#descend)
2894
2874
 
@@ -5635,7 +5615,7 @@ It splits `list` according to a provided `groupFn` function and returns an objec
5635
5615
 
5636
5616
  It returns separated version of list or string `input`, where separation is done with equality `compareFn` function.
5637
5617
 
5638
- <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20compareFn%20%3D%20(x%2C%20y)%20%3D%3E%20x%20%3D%3D%3D%20y%0Aconst%20list%20%3D%20%5B1%2C%202%2C%202%2C%201%2C%201%2C%202%5D%0A%0Aconst%20result%20%3D%20R.groupWith(isConsecutive%2C%20list)%0A%2F%2F%20%3D%3E%20%5B%5B1%5D%2C%20%5B2%2C2%5D%2C%20%5B1%2C1%5D%2C%20%5B2%5D%5D">Try this <strong>R.groupWith</strong> example in Rambda REPL</a>
5618
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20isConsecutive%20%3D%20(x%2C%20y)%20%3D%3E%20x%20%3D%3D%3D%20y%0Aconst%20list%20%3D%20%5B1%2C%202%2C%202%2C%201%2C%201%2C%202%5D%0A%0Aconst%20result%20%3D%20R.groupWith(isConsecutive%2C%20list)%0A%2F%2F%20%3D%3E%20%5B%5B1%5D%2C%20%5B2%2C2%5D%2C%20%5B1%2C1%5D%2C%20%5B2%5D%5D">Try this <strong>R.groupWith</strong> example in Rambda REPL</a>
5639
5619
 
5640
5620
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupWith)
5641
5621
 
@@ -5853,7 +5833,7 @@ describe('R.hasPath', () => {
5853
5833
  head(str: string): string
5854
5834
  ```
5855
5835
 
5856
- It returns the first element of list or string `input`.
5836
+ It returns the first element of list or string `input`. It returns `undefined` if array has length of 0.
5857
5837
 
5858
5838
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.head(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.head('foo')%20%0A%5D%0A%2F%2F%20%3D%3E%20%5B1%2C%20'f'%5D">Try this <strong>R.head</strong> example in Rambda REPL</a>
5859
5839
 
@@ -5864,6 +5844,7 @@ It returns the first element of list or string `input`.
5864
5844
  ```typescript
5865
5845
  head(str: string): string;
5866
5846
  head(str: ''): undefined;
5847
+ head(list: readonly[]): undefined;
5867
5848
  head<T>(list: never[]): undefined;
5868
5849
  head<T extends unknown[]>(array: T): FirstArrayElement<T>
5869
5850
  head<T extends readonly unknown[]>(array: T): FirstArrayElement<T>
@@ -5937,9 +5918,9 @@ describe('R.head', () => {
5937
5918
  it('empty array', () => {
5938
5919
  const list = [] as const
5939
5920
  head(emptyList) // $ExpectType undefined
5940
- head(list) // $ExpectType never
5921
+ head(list) // $ExpectType undefined
5941
5922
  last(emptyList) // $ExpectType undefined
5942
- last(list) // $ExpectType never
5923
+ last(list) // $ExpectType undefined
5943
5924
  })
5944
5925
 
5945
5926
  it('mixed', () => {
@@ -6076,10 +6057,9 @@ function ifElseFn(
6076
6057
  condition, onTrue, onFalse
6077
6058
  ){
6078
6059
  return (...input) => {
6079
- const conditionResult =
6060
+ const conditionResult =
6080
6061
  typeof condition === 'boolean' ? condition : condition(...input)
6081
-
6082
- if (conditionResult === true){
6062
+ if (Boolean(conditionResult) ){
6083
6063
  return onTrue(...input)
6084
6064
  }
6085
6065
 
@@ -6102,6 +6082,7 @@ import { has } from './has.js'
6102
6082
  import { identity } from './identity.js'
6103
6083
  import { ifElse } from './ifElse.js'
6104
6084
  import { prop } from './prop.js'
6085
+ import * as R from 'ramda'
6105
6086
 
6106
6087
  const condition = has('foo')
6107
6088
  const v = function (a){
@@ -6189,6 +6170,17 @@ test('simple arity of 2', () => {
6189
6170
  )(1, 10)
6190
6171
  expect(result).toBe(12)
6191
6172
  })
6173
+
6174
+ test('bug 750', () => {
6175
+ const value = 34;
6176
+
6177
+ let result = ifElse(
6178
+ R.identity,
6179
+ R.always('true'),
6180
+ R.always('false')
6181
+ )(value)
6182
+ expect(result).toBe('true')
6183
+ })
6192
6184
  ```
6193
6185
 
6194
6186
  </details>
@@ -6595,12 +6587,6 @@ export function isEmpty(input){
6595
6587
  return false
6596
6588
  if (!input) return true
6597
6589
 
6598
- if (type(input.isEmpty) === 'Function') {
6599
- return input.isEmpty();
6600
- } else if (input.isEmpty) {
6601
- return !!input.isEmpty;
6602
- }
6603
-
6604
6590
  if (inputType === 'Object'){
6605
6591
  return Object.keys(input).length === 0
6606
6592
  }
@@ -6635,10 +6621,6 @@ test('happy', () => {
6635
6621
  expect(isEmpty(0)).toBeFalse()
6636
6622
  expect(isEmpty(NaN)).toBeFalse()
6637
6623
  expect(isEmpty([ '' ])).toBeFalse()
6638
- expect(isEmpty({ isEmpty: false})).toBeFalse()
6639
- expect(isEmpty({ isEmpty: () => false})).toBeFalse()
6640
- expect(isEmpty({ isEmpty: true})).toBeTrue()
6641
- expect(isEmpty({ isEmpty: () => true})).toBeTrue()
6642
6624
  })
6643
6625
  ```
6644
6626
 
@@ -6716,6 +6698,27 @@ test('happy', () => {
6716
6698
 
6717
6699
  [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#isNil)
6718
6700
 
6701
+ ### isNotEmpty
6702
+
6703
+ ```typescript
6704
+
6705
+ isNotEmpty<T>(value: T[]): value is NonEmptyArray<T>
6706
+ ```
6707
+
6708
+ <details>
6709
+
6710
+ <summary>All TypeScript definitions</summary>
6711
+
6712
+ ```typescript
6713
+ isNotEmpty<T>(value: T[]): value is NonEmptyArray<T>;
6714
+ isNotEmpty<T>(value: readonly T[]): value is ReadonlyNonEmptyArray<T>;
6715
+ isNotEmpty(value: any): boolean;
6716
+ ```
6717
+
6718
+ </details>
6719
+
6720
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#isNotEmpty)
6721
+
6719
6722
  ### isNotNil
6720
6723
 
6721
6724
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.isNotNil(null)%2C%0A%20%20R.isNotNil(undefined)%2C%0A%20%20R.isNotNil(%5B%5D)%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5Bfalse%2C%20false%2C%20true%5D">Try this <strong>R.isNotNil</strong> example in Rambda REPL</a>
@@ -6930,7 +6933,7 @@ test('happy', () => {
6930
6933
  last(str: ''): undefined
6931
6934
  ```
6932
6935
 
6933
- It returns the last element of `input`, as the `input` can be either a string or an array.
6936
+ It returns the last element of `input`, as the `input` can be either a string or an array. It returns `undefined` if array has length of 0.
6934
6937
 
6935
6938
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20%5B%0A%20%20R.last(%5B1%2C%202%2C%203%5D)%2C%0A%20%20R.last('foo')%2C%0A%5D%0A%2F%2F%20%3D%3E%20%5B3%2C%20'o'%5D">Try this <strong>R.last</strong> example in Rambda REPL</a>
6936
6939
 
@@ -6941,9 +6944,11 @@ It returns the last element of `input`, as the `input` can be either a string or
6941
6944
  ```typescript
6942
6945
  last(str: ''): undefined;
6943
6946
  last(str: string): string;
6947
+ last(list: readonly[]): undefined;
6944
6948
  last(list: never[]): undefined;
6945
- last<T extends unknown[]>(array: T): LastArrayElement<T>
6946
- last<T extends readonly unknown[]>(array: T): LastArrayElement<T>
6949
+ last<T extends unknown[]>(array: T): LastArrayElement<T>;
6950
+ last<T extends readonly unknown[]>(array: T): LastArrayElement<T>;
6951
+ last(str: string): string | undefined;
6947
6952
  ```
6948
6953
 
6949
6954
  </details>
@@ -7251,7 +7256,7 @@ export function lens(getter, setter){
7251
7256
  <summary><strong>TypeScript</strong> test</summary>
7252
7257
 
7253
7258
  ```typescript
7254
- import {lens, assoc, lensProp, view, lensIndex, lensPath} from 'rambda'
7259
+ import {lens, assoc, lensProp, view, lensIndex, over, lensPath} from 'rambda'
7255
7260
 
7256
7261
  interface Input {
7257
7262
  foo: string,
@@ -7275,6 +7280,10 @@ describe('R.lensProp', () => {
7275
7280
  const result = view<Input, string>(lensProp('foo'), testObject)
7276
7281
  result // $ExpectType string
7277
7282
  })
7283
+ it('issue 740', () => {
7284
+ // @ts-expect-error
7285
+ over(lensProp('x'), (n) => String(n), {x: 1})
7286
+ })
7278
7287
  })
7279
7288
 
7280
7289
  describe('R.lensIndex', () => {
@@ -7587,7 +7596,7 @@ It returns the result of looping through `iterable` with `fn`.
7587
7596
 
7588
7597
  It works with both array and object.
7589
7598
 
7590
- <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20fn%20%3D%20x%20%3D%3E%20x%20*%202%0Aconst%20fnWhenObject%20%3D%20(val%2C%20prop)%3D%3E%7B%0A%20%20return%20%60%24%7Bprop%7D-%24%7Bval%7D%60%0A%7D%0A%0Aconst%20iterable%20%3D%20%5B1%2C%202%5D%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20%5B%20%0A%20%20R.map(fn%2C%20list)%2C%0A%20%20R.map(fnWhenObject%2C%20Record%3Cstring%2C%20unknown%3E)%0A%5D%0A%2F%2F%20%3D%3E%20%5B%20%5B1%2C%204%5D%2C%20%7Ba%3A%20'a-1'%2C%20b%3A%20'b-2'%7D%5D">Try this <strong>R.map</strong> example in Rambda REPL</a>
7599
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20fn%20%3D%20x%20%3D%3E%20x%20*%202%0Aconst%20fnWhenObject%20%3D%20(val%2C%20prop)%3D%3E%7B%0A%20%20return%20%60%24%7Bprop%7D-%24%7Bval%7D%60%0A%7D%0A%0Aconst%20iterable%20%3D%20%5B1%2C%202%5D%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20%5B%20%0A%20%20R.map(fn%2C%20iterable)%2C%0A%20%20R.map(fnWhenObject%2C%20obj)%0A%5D%0A%2F%2F%20%3D%3E%20%5B%20%5B2%2C%204%5D%2C%20%7Ba%3A%20'a-1'%2C%20b%3A%20'b-2'%7D%5D">Try this <strong>R.map</strong> example in Rambda REPL</a>
7591
7600
 
7592
7601
  <details>
7593
7602
 
@@ -7829,7 +7838,7 @@ mapObjIndexed<T>(fn: ObjectIterator<T, T>, iterable: Dictionary<T>): Dictionary<
7829
7838
 
7830
7839
  It works the same way as `R.map` does for objects. It is added as Ramda also has this method.
7831
7840
 
7832
- <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20fn%20%3D%20(val%2C%20prop)%20%3D%3E%20%7B%0A%20%20return%20%60%24%7Bprop%7D-%24%7Bval%7D%60%0A%7D%0A%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20R.map(mapObjIndexed%2C%20Record%3Cstring%2C%20unknown%3E)%0A%2F%2F%20%3D%3E%20%7Ba%3A%20'a-1'%2C%20b%3A%20'b-2'%7D">Try this <strong>R.mapObjIndexed</strong> example in Rambda REPL</a>
7841
+ <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20fn%20%3D%20(val%2C%20prop)%20%3D%3E%20%7B%0A%20%20return%20%60%24%7Bprop%7D-%24%7Bval%7D%60%0A%7D%0A%0Aconst%20obj%20%3D%20%7Ba%3A%201%2C%20b%3A%202%7D%0A%0Aconst%20result%20%3D%20R.mapObjIndexed(fn%2C%20obj)%0A%2F%2F%20%3D%3E%20%7Ba%3A%20'a-1'%2C%20b%3A%20'b-2'%7D">Try this <strong>R.mapObjIndexed</strong> example in Rambda REPL</a>
7833
7842
 
7834
7843
  <details>
7835
7844
 
@@ -8828,11 +8837,7 @@ It returns the lesser value between `x` and `y` according to `compareFn` functio
8828
8837
 
8829
8838
  ```typescript
8830
8839
 
8831
- modify<T extends object, K extends keyof T, P>(
8832
- prop: K,
8833
- fn: (a: T[K]) => P,
8834
- obj: T,
8835
- ): Omit<T, K> & Record<K, P>
8840
+ modify<K extends PropertyKey, T>(prop: K, fn: (value: T) => T): <U extends Record<K, T>>(object: U) => U
8836
8841
  ```
8837
8842
 
8838
8843
  <a title="redirect to Rambda Repl site" href="https://rambda.now.sh?const%20result%20%3D%20R.modify()%0A%2F%2F%20%3D%3E">Try this <strong>R.modify</strong> example in Rambda REPL</a>
@@ -8842,15 +8847,12 @@ modify<T extends object, K extends keyof T, P>(
8842
8847
  <summary>All TypeScript definitions</summary>
8843
8848
 
8844
8849
  ```typescript
8845
- modify<T extends object, K extends keyof T, P>(
8846
- prop: K,
8847
- fn: (a: T[K]) => P,
8848
- obj: T,
8849
- ): Omit<T, K> & Record<K, P>;
8850
- modify<K extends string, A, P>(
8851
- prop: K,
8852
- fn: (a: A) => P,
8853
- ): <T extends Record<K, A>>(target: T) => Omit<T, K> & Record<K, P>;
8850
+ modify<K extends PropertyKey, T>(prop: K, fn: (value: T) => T): <U extends Record<K, T>>(object: U) => U;
8851
+ modify<U, K extends keyof U>(prop: K, fn: (value: U[K]) => U[K], object: U): U;
8852
+ modify<K extends PropertyKey>(prop: K): {
8853
+ <T>(fn: (value: T) => T): <U extends Record<K, T>>(object: U) => U;
8854
+ <T, U extends Record<K, T>>(fn: (value: T) => T, object: U): U;
8855
+ };
8854
8856
  ```
8855
8857
 
8856
8858
  </details>
@@ -8991,23 +8993,52 @@ describe('brute force', () => {
8991
8993
  <summary><strong>TypeScript</strong> test</summary>
8992
8994
 
8993
8995
  ```typescript
8994
- import {modify, add} from 'rambda'
8995
- const person = {name: 'James', age: 20}
8996
+ import { add, identity, map, modify, pipe, toUpper } from 'rambda';
8997
+
8998
+ type Obj = {
8999
+ foo: string;
9000
+ bar: number;
9001
+ };
8996
9002
 
8997
9003
  describe('R.modify', () => {
8998
- it('happy', () => {
8999
- const {age} = modify('age', add(1), person)
9000
- const {age: ageAsString} = modify('age', String, person)
9004
+ it('ramda tests', () => {
9005
+ const result1 = modify('foo', toUpper, {} as Obj);
9006
+ result1; // $ExpectType Obj
9001
9007
 
9002
- age // $ExpectType number
9003
- ageAsString // $ExpectType string
9004
- })
9005
- it('curried', () => {
9006
- const {age} = modify('age', add(1))(person)
9008
+ const result2 = modify('bar', add(1), {} as Obj);
9009
+ result2; // $ExpectType Obj
9007
9010
 
9008
- age // $ExpectType number
9009
- })
9010
- })
9011
+ const result3 = modify('foo', toUpper)({} as Obj);
9012
+ result3; // $ExpectType Obj
9013
+
9014
+ const result4 = modify('bar', add(1))({} as Obj);
9015
+ result4; // $ExpectType Obj
9016
+
9017
+ const result5 = modify('foo')(toUpper)({} as Obj);
9018
+ result5; // $ExpectType Obj
9019
+
9020
+ const result6 = modify('bar')(add(1))({} as Obj);
9021
+ result6; // $ExpectType Obj
9022
+
9023
+ const result7 = modify('foo')(toUpper, {} as Obj);
9024
+ result7; // $ExpectType Obj
9025
+
9026
+ const result8 = modify('bar')(add(1), {} as Obj);
9027
+ result8; // $ExpectType Obj
9028
+
9029
+ const result9 = modify('foo', identity, {} as Obj);
9030
+ result9; // $ExpectType Obj
9031
+
9032
+ // @ts-expect-error
9033
+ modify('foo', add(1), {} as Obj);
9034
+ // @ts-expect-error
9035
+ modify('bar', toUpper, {} as Obj);
9036
+
9037
+ const f = pipe(map<Obj, Obj>(modify('foo', toUpper)));
9038
+
9039
+ f([] as Obj[]); // $ExpectType Obj[]
9040
+ });
9041
+ });
9011
9042
  ```
9012
9043
 
9013
9044
  </details>
@@ -17226,6 +17257,22 @@ describe('R.zipWith', () => {
17226
17257
 
17227
17258
  ## ❯ CHANGELOG
17228
17259
 
17260
+ 9.4.0
17261
+
17262
+ - Fix `deno` release
17263
+
17264
+ - Fix too strict `true` condition in `R.ifElse` - [Issue #750](https://github.com/selfrefactor/rambda/issues/750)
17265
+
17266
+ - Change `R.groupBy` typings to match `@types/ramda` typings
17267
+
17268
+ 9.3.0
17269
+
17270
+ - Breaking change in relation to TS typings of `R.assoc`, `R.dissoc` and `R.modify` - https://github.com/ramda/types/pull/37
17271
+
17272
+ - Add `R.isNotEmpty` as it is new method in `Ramda`
17273
+
17274
+ - Fix `R.head`/`R.last` TS definition - It returns `undefined` if array has length of 0. Before
17275
+
17229
17276
  9.2.1
17230
17277
 
17231
17278
  - Broken `Deno` build - [Issue #731](https://github.com/selfrefactor/rambda/issues/731)
@@ -17650,11 +17697,11 @@ Fix wrong versions in changelog
17650
17697
 
17651
17698
  > Links to Rambda
17652
17699
 
17653
- - [https://github.com/stoeffel/awesome-fp-js](awesome-fp-js)
17700
+ - [awesome-fp-js](https://github.com/stoeffel/awesome-fp-js)
17654
17701
 
17655
- - [ https://mailchi.mp/webtoolsweekly/web-tools-280 ]( Web Tools Weekly #280 )
17702
+ - [Web Tools Weekly #280](https://mailchi.mp/webtoolsweekly/web-tools-280)
17656
17703
 
17657
- - [https://github.com/docsifyjs/awesome-docsify](awesome-docsify)
17704
+ - [awesome-docsify](https://github.com/docsifyjs/awesome-docsify)
17658
17705
 
17659
17706
  > Deprecated from `Used by` section
17660
17707