From 86170e4d568ff25d360485b9e8a60dc76df8cf77 Mon Sep 17 00:00:00 2001 From: Deyan Totev Date: Sun, 14 Jan 2024 08:30:14 +0200 Subject: [PATCH] feat@build --- .github/README.md | 413 +++++++++----------------------------- CHANGELOG.md | 6 +- NEXT_VERSION_CHECKLIST.md | 7 +- README.md | 400 +++++++++--------------------------- dist/rambda.js | 70 ++++++- dist/rambda.umd.js | 2 +- immutable.d.ts | 97 +++++++-- index.d.ts | 97 +++++++-- rambda.js | 11 +- source/sortWith.spec.js | 2 - src/gt.js | 6 + src/gte.js | 6 + src/hasIn.js | 9 + src/innerJoin.js | 41 ++++ src/prop.js | 12 +- src/reduceBy.js | 29 +++ src/values.js | 2 - 17 files changed, 522 insertions(+), 688 deletions(-) create mode 100644 src/gt.js create mode 100644 src/gte.js create mode 100644 src/hasIn.js create mode 100644 src/innerJoin.js create mode 100644 src/reduceBy.js diff --git a/.github/README.md b/.github/README.md index 535864d70..b16342c7d 100644 --- a/.github/README.md +++ b/.github/README.md @@ -40,7 +40,15 @@ Still, you need to be aware that functional programming features in `TypeScript` Important - Rambda version `7.1.0`(or higher) requires TypeScript version `4.3.3`(or higher). -#### Immutable TS definitions +### Understandable source code due to little usage of internals + +`Ramda` uses a lot of internals, which hides a lot of logic. Reading the full source code of a method can be challenging. + +### Better VSCode experience + +If the project is written in Javascript, then `go to source definition` action will lead you to actual implementation of the method. + +### Immutable TS definitions You can use immutable version of Rambda definitions, which is linted with ESLint `functional/prefer-readonly-type` plugin. @@ -5899,6 +5907,14 @@ It returns separated version of list or string `input`, where separation is done [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupWith) +### gt + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#gt) + +### gte + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#gte) + ### has ```typescript @@ -5991,6 +6007,10 @@ describe('R.has', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#has) +### hasIn + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#hasIn) + ### hasPath ```typescript @@ -6827,6 +6847,10 @@ describe('R.init', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init) +### innerJoin + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#innerJoin) + ### intersection It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. @@ -7542,7 +7566,7 @@ test('with length as property', () => { ```typescript -lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens +lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens ``` It returns a `lens` for the given `getter` and `setter` functions. @@ -7566,7 +7590,7 @@ R.over(xLens, R.negate, {x: 1, y: 2}) // => {x: -1, y: 2} All TypeScript definitions ```typescript -lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens; +lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens; ``` @@ -7592,19 +7616,56 @@ export function lens(getter, setter){ TypeScript test ```typescript -import {lens, assoc} from 'rambda' +import {lens, assoc, lensProp, view, lensIndex, lensPath} from 'rambda' interface Input { foo: string, } +const testObject: Input = { + foo: 'Jazz', +} describe('R.lens', () => { it('happy', () => { - const fn = lens((x: Input) => { + const fn = lens((x: Input) => { x.foo // $ExpectType string return x.foo }, assoc('name')) - fn // $ExpectType Lens + fn // $ExpectType Lens + }) +}) + +describe('R.lensProp', () => { + it('happy', () => { + const result = view(lensProp('foo'), testObject) + result // $ExpectType string + }) +}) + +describe('R.lensIndex', () => { + const testList: Input[] = [{foo: 'bar'}, {foo: 'baz'}] + it('happy', () => { + const result = view(lensIndex(0), testList) + result // $ExpectType Input + result.foo // $ExpectType string + }) +}) + +describe('R.lensPath', () => { + const path = lensPath(['bar', 'a']) + it('happy', () => { + const result = view(path, testObject) + result // $ExpectType string + }) +}) + +describe('R.view', () => { + const fooLens = lens((x: Input) => { + return x.foo + }, assoc('foo')) + it('happt', () => { + const result = view(fooLens, testObject) + result // $ExpectType string }) }) ``` @@ -7617,7 +7678,7 @@ describe('R.lens', () => { ```typescript -lensIndex(index: number): Lens +lensIndex(n: number): Lens ``` It returns a lens that focuses on specified `index`. @@ -7638,7 +7699,8 @@ R.over(headLens, R.toUpper, list) // => ['A', 'b', 'c'] All TypeScript definitions ```typescript -lensIndex(index: number): Lens; +lensIndex(n: number): Lens; +lensIndex(n: N): Lens; ``` @@ -7724,263 +7786,21 @@ test('get (set(set s v1) v2) === v2', () => { -
- -TypeScript test - -```typescript -import {view, lensIndex} from 'rambda' - -interface Input { - a: number, -} -const testList: Input[] = [{a: 1}, {a: 2}, {a: 3}] - -describe('R.lensIndex', () => { - it('happy', () => { - const result = view(lensIndex(0), testList) - result // $ExpectType Input - result.a // $ExpectType number - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensIndex) ### lensPath -```typescript - -lensPath(path: RamdaPath): Lens -``` - It returns a lens that focuses on specified `path`. -```javascript -const lensPath = R.lensPath(['x', 0, 'y']) -const input = {x: [{y: 2, z: 3}, {y: 4, z: 5}]} - -R.view(lensPath, input) // => 2 - -R.set(lensPath, 1, input) -// => {x: [{y: 1, z: 3}, {y: 4, z: 5}]} - -R.over(xHeadYLens, R.negate, input) -// => {x: [{y: -2, z: 3}, {y: 4, z: 5}]} -``` -
Try this R.lensPath example in Rambda REPL -
- -All TypeScript definitions - -```typescript -lensPath(path: RamdaPath): Lens; -lensPath(path: string): Lens; -``` - -
- -
- -R.lensPath source - -```javascript -import { assocPath } from './assocPath.js' -import { lens } from './lens.js' -import { path } from './path.js' - -export function lensPath(key){ - return lens(path(key), assocPath(key)) -} -``` - -
- -
- -Tests - -```javascript -import { compose } from './compose.js' -import { identity } from './identity.js' -import { inc } from './inc.js' -import { lensPath } from './lensPath.js' -import { lensProp } from './lensProp.js' -import { over } from './over.js' -import { set } from './set.js' -import { view } from './view.js' - -const testObj = { - a : [ { b : 1 }, { b : 2 } ], - d : 3, -} - -test('view', () => { - expect(view(lensPath('d'), testObj)).toBe(3) - expect(view(lensPath('a.0.b'), testObj)).toBe(1) - // this is different to ramda, as ramda will return a clone of the input object - expect(view(lensPath(''), testObj)).toBeUndefined() -}) - -test('set', () => { - expect(set( - lensProp('d'), 0, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 0, - }) - expect(set( - lensPath('a.0.b'), 0, testObj - )).toEqual({ - a : [ { b : 0 }, { b : 2 } ], - d : 3, - }) - expect(set( - lensPath('a.0.X'), 0, testObj - )).toEqual({ - a : [ - { - b : 1, - X : 0, - }, - { b : 2 }, - ], - d : 3, - }) - expect(set( - lensPath([]), 0, testObj - )).toBe(0) -}) - -test('over', () => { - expect(over( - lensPath('d'), inc, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 4, - }) - expect(over( - lensPath('a.1.b'), inc, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 3 } ], - d : 3, - }) - expect(over( - lensProp('X'), identity, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 3, - X : undefined, - }) - expect(over( - lensPath('a.0.X'), identity, testObj - )).toEqual({ - a : [ - { - b : 1, - X : undefined, - }, - { b : 2 }, - ], - d : 3, - }) -}) - -test('compose', () => { - const composedLens = compose(lensPath('a'), lensPath('1.b')) - expect(view(composedLens, testObj)).toBe(2) -}) - -test('set s (get s) === s', () => { - expect(set( - lensPath([ 'd' ]), view(lensPath([ 'd' ]), testObj), testObj - )).toEqual(testObj) - expect(set( - lensPath([ 'a', 0, 'b' ]), - view(lensPath([ 'a', 0, 'b' ]), testObj), - testObj - )).toEqual(testObj) -}) - -test('get (set s v) === v', () => { - expect(view(lensPath([ 'd' ]), set( - lensPath([ 'd' ]), 0, testObj - ))).toBe(0) - expect(view(lensPath([ 'a', 0, 'b' ]), set( - lensPath([ 'a', 0, 'b' ]), 0, testObj - ))).toBe(0) -}) - -test('get (set(set s v1) v2) === v2', () => { - const p = [ 'd' ] - const q = [ 'a', 0, 'b' ] - expect(view(lensPath(p), set( - lensPath(p), 11, set( - lensPath(p), 10, testObj - ) - ))).toBe(11) - expect(view(lensPath(q), set( - lensPath(q), 11, set( - lensPath(q), 10, testObj - ) - ))).toBe(11) -}) -``` - -
- -
- -TypeScript test - -```typescript -import {lensPath, view} from 'rambda' - -interface Input { - foo: number[], - bar: { - a: string, - b: string, - }, -} - -const testObject: Input = { - foo: [1, 2], - bar: { - a: 'x', - b: 'y', - }, -} - -const path = lensPath(['bar', 'a']) -const pathAsString = lensPath('bar.a') - -describe('R.lensPath', () => { - it('happy', () => { - const result = view(path, testObject) - result // $ExpectType string - }) - it('using string as path input', () => { - const result = view(pathAsString, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensPath) ### lensProp ```typescript -lensProp(prop: string): { - (obj: T): U +lensProp(prop: K): Lens ``` It returns a lens that focuses on specified property `prop`. @@ -8005,10 +7825,7 @@ R.over(xLens, R.negate, input) All TypeScript definitions ```typescript -lensProp(prop: string): { - (obj: T): U; - set(val: T, obj: U): V; -}; +lensProp(prop: K): Lens; ``` @@ -8132,33 +7949,6 @@ test('get (set(set s v1) v2) === v2', () => { -
- -TypeScript test - -```typescript -import {lensProp, view} from 'rambda' - -interface Input { - foo: string, -} - -const testObject: Input = { - foo: 'Led Zeppelin', -} - -const lens = lensProp('foo') - -describe('R.lensProp', () => { - it('happy', () => { - const result = view(lens, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensProp) ### map @@ -12702,12 +12492,16 @@ prop(p: keyof never): (value: unknown) => V; R.prop source ```javascript -export function prop(propToFind, obj){ - if (arguments.length === 1) return _obj => prop(propToFind, _obj) - +export function propFn(searchProperty, obj){ if (!obj) return undefined - return obj[ propToFind ] + return obj[ searchProperty ] +} + +export function prop(searchProperty, obj){ + if (arguments.length === 1) return _obj => prop(searchProperty, _obj) + + return propFn(searchProperty, obj) } ``` @@ -13499,6 +13293,10 @@ describe('R.range', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduce) +### reduceBy + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduceBy) + ### reject ```typescript @@ -17546,8 +17344,6 @@ values(obj: T): T[K][]; import { type } from './type.js' export function values(obj){ - if (type(obj) !== 'Object') return [] - return Object.values(obj) } ``` @@ -17611,7 +17407,7 @@ describe('R.values', () => { ```typescript -view(lens: Lens): (target: T) => U +view(lens: Lens): (obj: S) => A ``` It returns the value of `lens` focus over `target` object. @@ -17630,8 +17426,8 @@ R.view(lens, {x: 4, y: 2}) // => 4 All TypeScript definitions ```typescript -view(lens: Lens): (target: T) => U; -view(lens: Lens, target: T): U; +view(lens: Lens): (obj: S) => A; +view(lens: Lens, obj: S): A; ``` @@ -17675,35 +17471,6 @@ test('happy', () => { -
- -TypeScript test - -```typescript -import {lens, view, assoc} from 'rambda' - -interface Input { - foo: string, -} - -const testObject: Input = { - foo: 'Led Zeppelin', -} - -const fooLens = lens((x: Input) => { - return x.foo -}, assoc('foo')) - -describe('R.view', () => { - it('happt', () => { - const result = view(fooLens, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#view) ### when @@ -18690,10 +18457,14 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -8.7.0 +9.0.0 + +Breaking change in TS definitions of `lenses` as now they are synced to `Ramda` types. - Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707) +- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn` + 8.6.0 - Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1276675ff..1ac317cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ -8.7.0 +9.0.0 + +Breaking change in TS definitions of `lenses` as now they are synced to `Ramda` types. - Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707) +- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn` + 8.6.0 - Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709) diff --git a/NEXT_VERSION_CHECKLIST.md b/NEXT_VERSION_CHECKLIST.md index af8c597c7..d599bbc12 100644 --- a/NEXT_VERSION_CHECKLIST.md +++ b/NEXT_VERSION_CHECKLIST.md @@ -1,10 +1,5 @@ -- innerJoin -- gt -- gte -- reduceBy -- hasIn -go to source definition in vscode works better for ramda than for rambda + --- https://developer.mozilla.org/en-US/docs/Web/API/structuredClone --- diff --git a/README.md b/README.md index 8de515263..987d9d5ef 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,15 @@ Still, you need to be aware that functional programming features in `TypeScript` Important - Rambda version `7.1.0`(or higher) requires TypeScript version `4.3.3`(or higher). -#### Immutable TS definitions +### Understandable source code due to little usage of internals + +`Ramda` uses a lot of internals, which hides a lot of logic. Reading the full source code of a method can be challenging. + +### Better VSCode experience + +If the project is written in Javascript, then `go to source definition` action will lead you to actual implementation of the method. + +### Immutable TS definitions You can use immutable version of Rambda definitions, which is linted with ESLint `functional/prefer-readonly-type` plugin. @@ -5600,6 +5608,14 @@ It returns separated version of list or string `input`, where separation is done [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupWith) +### gt + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#gt) + +### gte + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#gte) + ### has ```typescript @@ -5682,6 +5698,10 @@ describe('R.has', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#has) +### hasIn + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#hasIn) + ### hasPath ```typescript @@ -6460,6 +6480,10 @@ describe('R.init', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init) +### innerJoin + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#innerJoin) + ### intersection It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. @@ -7116,7 +7140,7 @@ test('with length as property', () => { ```typescript -lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens +lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens ``` It returns a `lens` for the given `getter` and `setter` functions. @@ -7132,7 +7156,7 @@ The setter should not mutate the data structure. All TypeScript definitions ```typescript -lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens; +lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens; ``` @@ -7158,19 +7182,56 @@ export function lens(getter, setter){ TypeScript test ```typescript -import {lens, assoc} from 'rambda' +import {lens, assoc, lensProp, view, lensIndex, lensPath} from 'rambda' interface Input { foo: string, } +const testObject: Input = { + foo: 'Jazz', +} describe('R.lens', () => { it('happy', () => { - const fn = lens((x: Input) => { + const fn = lens((x: Input) => { x.foo // $ExpectType string return x.foo }, assoc('name')) - fn // $ExpectType Lens + fn // $ExpectType Lens + }) +}) + +describe('R.lensProp', () => { + it('happy', () => { + const result = view(lensProp('foo'), testObject) + result // $ExpectType string + }) +}) + +describe('R.lensIndex', () => { + const testList: Input[] = [{foo: 'bar'}, {foo: 'baz'}] + it('happy', () => { + const result = view(lensIndex(0), testList) + result // $ExpectType Input + result.foo // $ExpectType string + }) +}) + +describe('R.lensPath', () => { + const path = lensPath(['bar', 'a']) + it('happy', () => { + const result = view(path, testObject) + result // $ExpectType string + }) +}) + +describe('R.view', () => { + const fooLens = lens((x: Input) => { + return x.foo + }, assoc('foo')) + it('happt', () => { + const result = view(fooLens, testObject) + result // $ExpectType string }) }) ``` @@ -7183,7 +7244,7 @@ describe('R.lens', () => { ```typescript -lensIndex(index: number): Lens +lensIndex(n: number): Lens ``` It returns a lens that focuses on specified `index`. @@ -7195,7 +7256,8 @@ It returns a lens that focuses on specified `index`. All TypeScript definitions ```typescript -lensIndex(index: number): Lens; +lensIndex(n: number): Lens; +lensIndex(n: N): Lens; ``` @@ -7281,250 +7343,21 @@ test('get (set(set s v1) v2) === v2', () => { -
- -TypeScript test - -```typescript -import {view, lensIndex} from 'rambda' - -interface Input { - a: number, -} -const testList: Input[] = [{a: 1}, {a: 2}, {a: 3}] - -describe('R.lensIndex', () => { - it('happy', () => { - const result = view(lensIndex(0), testList) - result // $ExpectType Input - result.a // $ExpectType number - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensIndex) ### lensPath -```typescript - -lensPath(path: RamdaPath): Lens -``` - It returns a lens that focuses on specified `path`.
Try this R.lensPath example in Rambda REPL -
- -All TypeScript definitions - -```typescript -lensPath(path: RamdaPath): Lens; -lensPath(path: string): Lens; -``` - -
- -
- -R.lensPath source - -```javascript -import { assocPath } from './assocPath.js' -import { lens } from './lens.js' -import { path } from './path.js' - -export function lensPath(key){ - return lens(path(key), assocPath(key)) -} -``` - -
- -
- -Tests - -```javascript -import { compose } from './compose.js' -import { identity } from './identity.js' -import { inc } from './inc.js' -import { lensPath } from './lensPath.js' -import { lensProp } from './lensProp.js' -import { over } from './over.js' -import { set } from './set.js' -import { view } from './view.js' - -const testObj = { - a : [ { b : 1 }, { b : 2 } ], - d : 3, -} - -test('view', () => { - expect(view(lensPath('d'), testObj)).toBe(3) - expect(view(lensPath('a.0.b'), testObj)).toBe(1) - // this is different to ramda, as ramda will return a clone of the input object - expect(view(lensPath(''), testObj)).toBeUndefined() -}) - -test('set', () => { - expect(set( - lensProp('d'), 0, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 0, - }) - expect(set( - lensPath('a.0.b'), 0, testObj - )).toEqual({ - a : [ { b : 0 }, { b : 2 } ], - d : 3, - }) - expect(set( - lensPath('a.0.X'), 0, testObj - )).toEqual({ - a : [ - { - b : 1, - X : 0, - }, - { b : 2 }, - ], - d : 3, - }) - expect(set( - lensPath([]), 0, testObj - )).toBe(0) -}) - -test('over', () => { - expect(over( - lensPath('d'), inc, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 4, - }) - expect(over( - lensPath('a.1.b'), inc, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 3 } ], - d : 3, - }) - expect(over( - lensProp('X'), identity, testObj - )).toEqual({ - a : [ { b : 1 }, { b : 2 } ], - d : 3, - X : undefined, - }) - expect(over( - lensPath('a.0.X'), identity, testObj - )).toEqual({ - a : [ - { - b : 1, - X : undefined, - }, - { b : 2 }, - ], - d : 3, - }) -}) - -test('compose', () => { - const composedLens = compose(lensPath('a'), lensPath('1.b')) - expect(view(composedLens, testObj)).toBe(2) -}) - -test('set s (get s) === s', () => { - expect(set( - lensPath([ 'd' ]), view(lensPath([ 'd' ]), testObj), testObj - )).toEqual(testObj) - expect(set( - lensPath([ 'a', 0, 'b' ]), - view(lensPath([ 'a', 0, 'b' ]), testObj), - testObj - )).toEqual(testObj) -}) - -test('get (set s v) === v', () => { - expect(view(lensPath([ 'd' ]), set( - lensPath([ 'd' ]), 0, testObj - ))).toBe(0) - expect(view(lensPath([ 'a', 0, 'b' ]), set( - lensPath([ 'a', 0, 'b' ]), 0, testObj - ))).toBe(0) -}) - -test('get (set(set s v1) v2) === v2', () => { - const p = [ 'd' ] - const q = [ 'a', 0, 'b' ] - expect(view(lensPath(p), set( - lensPath(p), 11, set( - lensPath(p), 10, testObj - ) - ))).toBe(11) - expect(view(lensPath(q), set( - lensPath(q), 11, set( - lensPath(q), 10, testObj - ) - ))).toBe(11) -}) -``` - -
- -
- -TypeScript test - -```typescript -import {lensPath, view} from 'rambda' - -interface Input { - foo: number[], - bar: { - a: string, - b: string, - }, -} - -const testObject: Input = { - foo: [1, 2], - bar: { - a: 'x', - b: 'y', - }, -} - -const path = lensPath(['bar', 'a']) -const pathAsString = lensPath('bar.a') - -describe('R.lensPath', () => { - it('happy', () => { - const result = view(path, testObject) - result // $ExpectType string - }) - it('using string as path input', () => { - const result = view(pathAsString, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensPath) ### lensProp ```typescript -lensProp(prop: string): { - (obj: T): U +lensProp(prop: K): Lens ``` It returns a lens that focuses on specified property `prop`. @@ -7536,10 +7369,7 @@ It returns a lens that focuses on specified property `prop`. All TypeScript definitions ```typescript -lensProp(prop: string): { - (obj: T): U; - set(val: T, obj: U): V; -}; +lensProp(prop: K): Lens; ``` @@ -7663,33 +7493,6 @@ test('get (set(set s v1) v2) === v2', () => { -
- -TypeScript test - -```typescript -import {lensProp, view} from 'rambda' - -interface Input { - foo: string, -} - -const testObject: Input = { - foo: 'Led Zeppelin', -} - -const lens = lensProp('foo') - -describe('R.lensProp', () => { - it('happy', () => { - const result = view(lens, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensProp) ### map @@ -11891,12 +11694,16 @@ prop(p: keyof never): (value: unknown) => V; R.prop source ```javascript -export function prop(propToFind, obj){ - if (arguments.length === 1) return _obj => prop(propToFind, _obj) - +export function propFn(searchProperty, obj){ if (!obj) return undefined - return obj[ propToFind ] + return obj[ searchProperty ] +} + +export function prop(searchProperty, obj){ + if (arguments.length === 1) return _obj => prop(searchProperty, _obj) + + return propFn(searchProperty, obj) } ``` @@ -12627,6 +12434,10 @@ describe('R.range', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduce) +### reduceBy + +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduceBy) + ### reject ```typescript @@ -16342,8 +16153,6 @@ values(obj: T): T[K][]; import { type } from './type.js' export function values(obj){ - if (type(obj) !== 'Object') return [] - return Object.values(obj) } ``` @@ -16407,7 +16216,7 @@ describe('R.values', () => { ```typescript -view(lens: Lens): (target: T) => U +view(lens: Lens): (obj: S) => A ``` It returns the value of `lens` focus over `target` object. @@ -16419,8 +16228,8 @@ It returns the value of `lens` focus over `target` object. All TypeScript definitions ```typescript -view(lens: Lens): (target: T) => U; -view(lens: Lens, target: T): U; +view(lens: Lens): (obj: S) => A; +view(lens: Lens, obj: S): A; ``` @@ -16464,35 +16273,6 @@ test('happy', () => { -
- -TypeScript test - -```typescript -import {lens, view, assoc} from 'rambda' - -interface Input { - foo: string, -} - -const testObject: Input = { - foo: 'Led Zeppelin', -} - -const fooLens = lens((x: Input) => { - return x.foo -}, assoc('foo')) - -describe('R.view', () => { - it('happt', () => { - const result = view(fooLens, testObject) - result // $ExpectType string - }) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#view) ### when @@ -17404,10 +17184,14 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -8.7.0 +9.0.0 + +Breaking change in TS definitions of `lenses` as now they are synced to `Ramda` types. - Add `R.sortWith` - [Issue #707](https://github.com/selfrefactor/rambda/issues/707) +- Add `R.innerJoin`, `R.gt`, `R.gte`, `R.reduceBy`, `R.hasIn` + 8.6.0 - Wrong typing for `R.dissocPath` - [Issue #709](https://github.com/selfrefactor/rambda/issues/709) diff --git a/dist/rambda.js b/dist/rambda.js index 521f4b90f..3f57fc3e1 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -1116,10 +1116,13 @@ function eqByFn(fn, a, b) { } const eqBy = curry(eqByFn); -function prop(propToFind, obj) { - if (arguments.length === 1) return _obj => prop(propToFind, _obj); +function propFn(searchProperty, obj) { if (!obj) return undefined; - return obj[propToFind]; + return obj[searchProperty]; +} +function prop(searchProperty, obj) { + if (arguments.length === 1) return _obj => prop(searchProperty, _obj); + return propFn(searchProperty, obj); } function eqPropsFn(property, objA, objB) { @@ -1360,12 +1363,29 @@ function groupWith(compareFn, list) { return toReturn; } +function gt(a, b) { + if (arguments.length === 1) return _b => gt(a, _b); + return a > b; +} + +function gte(a, b) { + if (arguments.length === 1) return _b => gte(a, _b); + return a >= b; +} + function has(prop, obj) { if (arguments.length === 1) return _obj => has(prop, _obj); if (!obj) return false; return obj.hasOwnProperty(prop); } +function hasIn(searchProperty, obj) { + if (arguments.length === 1) { + return _obj => hasIn(searchProperty, _obj); + } + return propFn(searchProperty, obj) !== undefined; +} + function hasPath(pathInput, obj) { if (arguments.length === 1) { return objHolder => hasPath(pathInput, objHolder); @@ -1452,6 +1472,30 @@ function init(listOrString) { return listOrString.length ? baseSlice(listOrString, 0, -1) : []; } +function _includesWith(pred, x, list) { + let idx = 0; + const len = list.length; + while (idx < len) { + if (pred(x, list[idx])) return true; + idx += 1; + } + return false; +} +function _filter(fn, list) { + let idx = 0; + const len = list.length; + const result = []; + while (idx < len) { + if (fn(list[idx])) result[result.length] = list[idx]; + idx += 1; + } + return result; +} +function innerJoinFn(pred, xs, ys) { + return _filter(x => _includesWith(pred, x, ys), xs); +} +const innerJoin = curry(innerJoinFn); + function intersection(listA, listB) { if (arguments.length === 1) return _list => intersection(listA, _list); return filter(x => includes$1(x, listA), listB); @@ -1942,6 +1986,17 @@ function range(start, end) { return willReturn; } +function reduceByFunction(valueFn, valueAcc, keyFn, acc, elt) { + const key = keyFn(elt); + const value = valueFn(has(key, acc) ? acc[key] : clone(valueAcc), elt); + acc[key] = value; + return acc; +} +function reduceByFn(valueFn, valueAcc, keyFn, list) { + return reduce((acc, elt) => reduceByFunction(valueFn, valueAcc, keyFn, acc, elt), {}, list); +} +const reduceBy = curry(reduceByFn); + function reject(predicate, list) { if (arguments.length === 1) return _list => reject(predicate, _list); return filter(x => !predicate(x), list); @@ -2280,7 +2335,6 @@ function unwind(property, obj) { } function values(obj) { - if (type(obj) !== 'Object') return []; return Object.values(obj); } @@ -2457,7 +2511,10 @@ exports.forEachObjIndexedFn = forEachObjIndexedFn; exports.fromPairs = fromPairs; exports.groupBy = groupBy; exports.groupWith = groupWith; +exports.gt = gt; +exports.gte = gte; exports.has = has; +exports.hasIn = hasIn; exports.hasPath = hasPath; exports.head = head; exports.identical = identical; @@ -2468,6 +2525,8 @@ exports.includes = includes$1; exports.indexBy = indexBy; exports.indexOf = indexOf; exports.init = init; +exports.innerJoin = innerJoin; +exports.innerJoinFn = innerJoinFn; exports.intersection = intersection; exports.intersperse = intersperse; exports.is = is; @@ -2540,12 +2599,15 @@ exports.prepend = prepend; exports.product = product; exports.prop = prop; exports.propEq = propEq; +exports.propFn = propFn; exports.propIs = propIs; exports.propOr = propOr; exports.propSatisfies = propSatisfies; exports.props = props; exports.range = range; exports.reduce = reduce; +exports.reduceBy = reduceBy; +exports.reduceByFn = reduceByFn; exports.reduceFn = reduceFn; exports.reduceStopper = reduceStopper; exports.reject = reject; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 39505d3ec..c18a15c29 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -1 +1 @@ -!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r((n="undefined"!=typeof globalThis?globalThis:n||self).R={})}(this,function(n){"use strict";function a(n,l){switch(n){case 0:return function(){return l.apply(this,arguments)};case 1:return function(n){return l.apply(this,arguments)};case 2:return function(n,r){return l.apply(this,arguments)};case 3:return function(n,r,t){return l.apply(this,arguments)};case 4:return function(n,r,t,e){return l.apply(this,arguments)};case 5:return function(n,r,t,e,u){return l.apply(this,arguments)};case 6:return function(n,r,t,e,u,i){return l.apply(this,arguments)};case 7:return function(n,r,t,e,u,i,o){return l.apply(this,arguments)};case 8:return function(n,r,t,e,u,i,o,f){return l.apply(this,arguments)};case 9:return function(n,r,t,e,u,i,o,f,c){return l.apply(this,arguments)};default:return function(n,r,t,e,u,i,o,f,c,a){return l.apply(this,arguments)}}}function t(r,n){if(1===arguments.length)return function(n){return t(r,n)};if(10>>0,r>>>=0,Array(u));++en(r)?t:r}var Dn=c(Un);function Ln(n){return n.reduce(function(n,r){return n+r},0)}function zn(n){return Ln(n)/n.length}function W(r,n){return 1===arguments.length?function(n){return W(r,n)}:Object.assign({},r||{},n||{})}function q(r,t){var e;return 1===arguments.length?function(n){return q(r,n)}:(e=Q(r),Object.keys(t).forEach(function(n){"Object"===N(t[n])&&"Object"===N(r[n])?e[n]=q(r[n],t[n]):e[n]=t[n]}),e)}function _n(r,n,t){var e=null!=n?n:{},u=null!=t?t:{},i={};return Object.keys(e).forEach(function(n){i[n]=void 0===u[n]?e[n]:r(e[n],u[n])}),Object.keys(u).forEach(function(n){void 0===i[n]&&(i[n]=void 0===e[n]?u[n]:r(e[n],u[n]))}),i}var Mn=c(_n);function Hn(n,r,t){return n(t) 4")};var e},n.forEach=function r(t,n){if(1===arguments.length)return function(n){return r(t,n)};if(void 0!==n){if(!p(n))return In(t,n);for(var e=0,u=n.length;e>>0,r>>>=0,Array(u));++en(r)?t:r}var Mn=c(_n);function Jn(n){return n.reduce(function(n,r){return n+r},0)}function Hn(n){return Jn(n)/n.length}function W(r,n){return 1===arguments.length?function(n){return W(r,n)}:Object.assign({},r||{},n||{})}function B(r,t){var e;return 1===arguments.length?function(n){return B(r,n)}:(e=b(r),Object.keys(t).forEach(function(n){"Object"===N(t[n])&&"Object"===N(r[n])?e[n]=B(r[n],t[n]):e[n]=t[n]}),e)}function $n(r,n,t){var e=null!=n?n:{},u=null!=t?t:{},i={};return Object.keys(e).forEach(function(n){i[n]=void 0===u[n]?e[n]:r(e[n],u[n])}),Object.keys(u).forEach(function(n){void 0===i[n]&&(i[n]=void 0===e[n]?u[n]:r(e[n],u[n]))}),i}var Gn=c($n);function Kn(n,r,t){return n(t) 4")};var e},n.forEach=function r(t,n){if(1===arguments.length)return function(n){return r(t,n)};if(void 0!==n){if(!p(n))return Wn(t,n);for(var e=0,u=n.length;e extends Array { readonly 1: V; } -export interface Lens { - (obj: T): U; - set(str: string, obj: T): U; -} +export type Lens = (functorFactory: (a: A) => Functor) => (s: S) => Functor; type Arity1Fn = (x: any) => any; type Arity2Fn = (x: any, y: any) => any; @@ -147,12 +144,12 @@ interface SchemaAsync { readonly [key: string]: Promise; } -interface IsValid { +export interface IsValid { readonly input: object; readonly schema: Schema; } -interface IsValidAsync { +export interface IsValidAsync { readonly input: object; readonly schema: Schema | SchemaAsync; } @@ -174,8 +171,6 @@ type ApplyDiffAdd = {readonly op:'add', readonly path: string, readonly value: a type ApplyDiffRemove = {readonly op:'remove', readonly path: string}; type ApplyDiffRule = ApplyDiffUpdate | ApplyDiffAdd | ApplyDiffRemove; -type Resolved = {readonly status: 'fulfilled', readonly value: T} | {readonly status: 'rejected', readonly reason: string|Error} - export function F(): boolean; @@ -686,12 +681,19 @@ export function groupWith(compareFn: (x: T, y: T) => boolean): (input: readon export function groupWith(compareFn: (x: T, y: T) => boolean, input: readonly T[]): readonly ((readonly T[]))[]; export function groupWith(compareFn: (x: T, y: T) => boolean, input: string): readonly string[]; +export function gt(x: T): T; + +export function gte(x: T): T; + /** * It returns `true` if `obj` has property `prop`. */ export function has(prop: string, obj: T): boolean; export function has(prop: string): (obj: T) => boolean; +export function hasIn(searchProperty: string): (obj: T) => boolean; +export function hasIn(searchProperty: string, obj: T): boolean; + /** * It will return true, if `input` object has truthy `path`(calculated with `R.path`). */ @@ -780,6 +782,15 @@ export function indexOf(valueToFind: T): (list: readonly T[]) => number; export function init(input: T): T extends readonly [...infer U, any] ? U : readonly [...T]; export function init(input: string): string; +export function innerJoin( + pred: (a: T1, b: T2) => boolean, +): (list1: readonly T1[], list2: readonly T2[]) => readonly T1[]; +export function innerJoin( + pred: (a: T1, b: T2) => boolean, + list1: readonly T1[], +): (list2: readonly T2[]) => readonly T1[]; +export function innerJoin(pred: (a: T1, b: T2) => boolean, list1: readonly T1[], list2: readonly T2[]): readonly T1[]; + /** * It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. */ @@ -863,26 +874,57 @@ export function length(input: readonly T[]): number; * * The setter should not mutate the data structure. */ -export function lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens; +export function lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens; /** * It returns a lens that focuses on specified `index`. */ -export function lensIndex(index: number): Lens; +export function lensIndex(n: number): Lens; +export function lensIndex(n: N): Lens; /** * It returns a lens that focuses on specified `path`. */ -export function lensPath(path: RamdaPath): Lens; -export function lensPath(path: string): Lens; +export function lensPath(path: readonly [K0]): Lens; +export function lensPath( + path: readonly [K0, K1], +): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1] +>(path: readonly [K0, K1, K2]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2] +>(path: readonly [K0, K1, K2, K3]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2], + K4 extends keyof S[K0][K1][K2][K3] = keyof S[K0][K1][K2][K3] +>(path: readonly [K0, K1, K2, K3, K4]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2], + K4 extends keyof S[K0][K1][K2][K3] = keyof S[K0][K1][K2][K3], + K5 extends keyof S[K0][K1][K2][K3][K4] = keyof S[K0][K1][K2][K3][K4] +>(path: readonly [K0, K1, K2, K3, K4, K5]): Lens; +export function lensPath(path: Path): Lens; /** * It returns a lens that focuses on specified property `prop`. */ -export function lensProp(prop: string): { - (obj: T): U; - set(val: T, obj: U): V; -}; +export function lensProp(prop: K): Lens; /** * It returns the result of looping through `iterable` with `fn`. @@ -1393,6 +1435,25 @@ export function reduce(reducer: (prev: TResult, current: T) => TResu export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult): (initialValue: TResult, list: readonly T[]) => TResult; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: readonly T[]) => TResult; +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, +): (a: TResult, b: (elem: T) => string, c: readonly T[]) => { readonly [index: string]: TResult } +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, +): (a: (elem: T) => string, b: readonly T[]) => { readonly [index: string]: TResult } +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, + keyFn: (elem: T) => string, +): (list: readonly T[]) => { readonly [index: string]: TResult }; +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, + keyFn: (elem: T) => string, + list: readonly T[], +): { readonly [index: string]: TResult }; + /** * It has the opposite effect of `R.filter`. */ @@ -1687,8 +1748,8 @@ export function values(obj: T): readonly T[ /** * It returns the value of `lens` focus over `target` object. */ -export function view(lens: Lens): (target: T) => U; -export function view(lens: Lens, target: T): U; +export function view(lens: Lens): (obj: S) => A; +export function view(lens: Lens, obj: S): A; export function when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U; export function when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U): (input: T) => T | U; diff --git a/index.d.ts b/index.d.ts index 744d61176..dd2348fe9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -43,10 +43,7 @@ interface KeyValuePair extends Array { 1: V; } -export interface Lens { - (obj: T): U; - set(str: string, obj: T): U; -} +export type Lens = (functorFactory: (a: A) => Functor) => (s: S) => Functor; type Arity1Fn = (x: any) => any; type Arity2Fn = (x: any, y: any) => any; @@ -147,12 +144,12 @@ interface SchemaAsync { [key: string]: Promise; } -interface IsValid { +export interface IsValid { input: object; schema: Schema; } -interface IsValidAsync { +export interface IsValidAsync { input: object; schema: Schema | SchemaAsync; } @@ -174,8 +171,6 @@ type ApplyDiffAdd = {op:'add', path: string, value: any}; type ApplyDiffRemove = {op:'remove', path: string}; type ApplyDiffRule = ApplyDiffUpdate | ApplyDiffAdd | ApplyDiffRemove; -type Resolved = {status: 'fulfilled', value: T} | {status: 'rejected', reason: string|Error} - export function F(): boolean; @@ -686,12 +681,19 @@ export function groupWith(compareFn: (x: T, y: T) => boolean): (input: T[]) = export function groupWith(compareFn: (x: T, y: T) => boolean, input: T[]): (T[])[]; export function groupWith(compareFn: (x: T, y: T) => boolean, input: string): string[]; +export function gt(x: T): T; + +export function gte(x: T): T; + /** * It returns `true` if `obj` has property `prop`. */ export function has(prop: string, obj: T): boolean; export function has(prop: string): (obj: T) => boolean; +export function hasIn(searchProperty: string): (obj: T) => boolean; +export function hasIn(searchProperty: string, obj: T): boolean; + /** * It will return true, if `input` object has truthy `path`(calculated with `R.path`). */ @@ -780,6 +782,15 @@ export function indexOf(valueToFind: T): (list: T[]) => number; export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; export function init(input: string): string; +export function innerJoin( + pred: (a: T1, b: T2) => boolean, +): (list1: T1[], list2: T2[]) => T1[]; +export function innerJoin( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[]; +export function innerJoin(pred: (a: T1, b: T2) => boolean, list1: T1[], list2: T2[]): T1[]; + /** * It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. */ @@ -863,26 +874,57 @@ export function length(input: T[]): number; * * The setter should not mutate the data structure. */ -export function lens(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens; +export function lens(getter: (s: S) => A, setter: (a: A, s: S) => S): Lens; /** * It returns a lens that focuses on specified `index`. */ -export function lensIndex(index: number): Lens; +export function lensIndex(n: number): Lens; +export function lensIndex(n: N): Lens; /** * It returns a lens that focuses on specified `path`. */ -export function lensPath(path: RamdaPath): Lens; -export function lensPath(path: string): Lens; +export function lensPath(path: [K0]): Lens; +export function lensPath( + path: [K0, K1], +): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1] +>(path: [K0, K1, K2]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2] +>(path: [K0, K1, K2, K3]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2], + K4 extends keyof S[K0][K1][K2][K3] = keyof S[K0][K1][K2][K3] +>(path: [K0, K1, K2, K3, K4]): Lens; +export function lensPath< + S, + K0 extends keyof S = keyof S, + K1 extends keyof S[K0] = keyof S[K0], + K2 extends keyof S[K0][K1] = keyof S[K0][K1], + K3 extends keyof S[K0][K1][K2] = keyof S[K0][K1][K2], + K4 extends keyof S[K0][K1][K2][K3] = keyof S[K0][K1][K2][K3], + K5 extends keyof S[K0][K1][K2][K3][K4] = keyof S[K0][K1][K2][K3][K4] +>(path: [K0, K1, K2, K3, K4, K5]): Lens; +export function lensPath(path: Path): Lens; /** * It returns a lens that focuses on specified property `prop`. */ -export function lensProp(prop: string): { - (obj: T): U; - set(val: T, obj: U): V; -}; +export function lensProp(prop: K): Lens; /** * It returns the result of looping through `iterable` with `fn`. @@ -1393,6 +1435,25 @@ export function reduce(reducer: (prev: TResult, current: T) => TResu export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult): (initialValue: TResult, list: T[]) => TResult; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult; +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, +): (a: TResult, b: (elem: T) => string, c: T[]) => { [index: string]: TResult } +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, +): (a: (elem: T) => string, b: T[]) => { [index: string]: TResult } +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, + keyFn: (elem: T) => string, +): (list: T[]) => { [index: string]: TResult }; +export function reduceBy( + valueFn: (acc: TResult, elem: T) => TResult, + acc: TResult, + keyFn: (elem: T) => string, + list: T[], +): { [index: string]: TResult }; + /** * It has the opposite effect of `R.filter`. */ @@ -1687,8 +1748,8 @@ export function values(obj: T): T[K][]; /** * It returns the value of `lens` focus over `target` object. */ -export function view(lens: Lens): (target: T) => U; -export function view(lens: Lens, target: T): U; +export function view(lens: Lens): (obj: S) => A; +export function view(lens: Lens, obj: S): A; export function when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U; export function when(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U): (input: T) => T | U; diff --git a/rambda.js b/rambda.js index f08aceeb8..7cc47d7d7 100644 --- a/rambda.js +++ b/rambda.js @@ -1,4 +1,6 @@ /// +export * from './src/F.js' +export * from './src/T.js' export * from './src/add.js' export * from './src/addIndex.js' export * from './src/addIndexRight.js' @@ -59,7 +61,6 @@ export * from './src/eqBy.js' export * from './src/eqProps.js' export * from './src/equals.js' export * from './src/evolve.js' -export * from './src/F.js' export * from './src/filter.js' export * from './src/find.js' export * from './src/findIndex.js' @@ -72,7 +73,10 @@ export * from './src/forEachObjIndexed.js' export * from './src/fromPairs.js' export * from './src/groupBy.js' export * from './src/groupWith.js' +export * from './src/gt.js' +export * from './src/gte.js' export * from './src/has.js' +export * from './src/hasIn.js' export * from './src/hasPath.js' export * from './src/head.js' export * from './src/identical.js' @@ -83,6 +87,7 @@ export * from './src/includes.js' export * from './src/indexBy.js' export * from './src/indexOf.js' export * from './src/init.js' +export * from './src/innerJoin.js' export * from './src/intersection.js' export * from './src/intersperse.js' export * from './src/is.js' @@ -146,10 +151,11 @@ export * from './src/prop.js' export * from './src/propEq.js' export * from './src/propIs.js' export * from './src/propOr.js' -export * from './src/props.js' export * from './src/propSatisfies.js' +export * from './src/props.js' export * from './src/range.js' export * from './src/reduce.js' +export * from './src/reduceBy.js' export * from './src/reject.js' export * from './src/removeIndex.js' export * from './src/repeat.js' @@ -168,7 +174,6 @@ export * from './src/startsWith.js' export * from './src/subtract.js' export * from './src/sum.js' export * from './src/symmetricDifference.js' -export * from './src/T.js' export * from './src/tail.js' export * from './src/take.js' export * from './src/takeLast.js' diff --git a/source/sortWith.spec.js b/source/sortWith.spec.js index 58e9de3ff..57dcfa038 100644 --- a/source/sortWith.spec.js +++ b/source/sortWith.spec.js @@ -1,5 +1,3 @@ -import { sortWith as sortWithRamda } from 'ramda' - import { ascend, prop } from '../rambda.js' import { sortWith } from './sortWith.js' diff --git a/src/gt.js b/src/gt.js new file mode 100644 index 000000000..7195da324 --- /dev/null +++ b/src/gt.js @@ -0,0 +1,6 @@ +export function gt(a, b){ + if (arguments.length === 1) + return _b => gt(a, _b) + + return a > b +} diff --git a/src/gte.js b/src/gte.js new file mode 100644 index 000000000..f5ec066c7 --- /dev/null +++ b/src/gte.js @@ -0,0 +1,6 @@ +export function gte(a, b){ + if (arguments.length === 1) + return _b => gte(a, _b) + + return a >= b +} diff --git a/src/hasIn.js b/src/hasIn.js new file mode 100644 index 000000000..cdbc7045a --- /dev/null +++ b/src/hasIn.js @@ -0,0 +1,9 @@ +import { propFn } from "./prop"; + +export function hasIn(searchProperty, obj) { + if (arguments.length === 1){ + return (_obj) => hasIn(searchProperty, _obj); + } + + return propFn(searchProperty, obj) !== undefined +} \ No newline at end of file diff --git a/src/innerJoin.js b/src/innerJoin.js new file mode 100644 index 000000000..1be66e63d --- /dev/null +++ b/src/innerJoin.js @@ -0,0 +1,41 @@ +import { curry } from './curry.js' + +function _includesWith( + pred, x, list +){ + let idx = 0 + const len = list.length + + while (idx < len){ + if (pred(x, list[ idx ])) + return true + + idx += 1 + } + + return false +} +function _filter(fn, list){ + let idx = 0 + const len = list.length + const result = [] + + while (idx < len){ + if (fn(list[ idx ])) + result[ result.length ] = list[ idx ] + + idx += 1 + } + + return result +} + +export function innerJoinFn( + pred, xs, ys +){ + return _filter(x => _includesWith( + pred, x, ys + ), xs) +} + +export const innerJoin = curry(innerJoinFn) diff --git a/src/prop.js b/src/prop.js index 37fae1ea1..8a6bce516 100644 --- a/src/prop.js +++ b/src/prop.js @@ -1,7 +1,11 @@ -export function prop(propToFind, obj){ - if (arguments.length === 1) return _obj => prop(propToFind, _obj) - +export function propFn(searchProperty, obj){ if (!obj) return undefined - return obj[ propToFind ] + return obj[ searchProperty ] +} + +export function prop(searchProperty, obj){ + if (arguments.length === 1) return _obj => prop(searchProperty, _obj) + + return propFn(searchProperty, obj) } diff --git a/src/reduceBy.js b/src/reduceBy.js new file mode 100644 index 000000000..d36aae444 --- /dev/null +++ b/src/reduceBy.js @@ -0,0 +1,29 @@ +import { clone } from './clone.js' +import { curry } from './curry.js' +import { has } from './has.js' +import { reduce } from './reduce.js' + +function reduceByFunction( + valueFn, valueAcc, keyFn, acc, elt +){ + const key = keyFn(elt) + const value = valueFn(has(key, acc) ? acc[ key ] : clone(valueAcc), elt) + + acc[ key ] = value + + return acc +} + +export function reduceByFn( + valueFn, valueAcc, keyFn, list +){ + return reduce( + (acc, elt) => reduceByFunction( + valueFn, valueAcc, keyFn, acc, elt + ), + {}, + list + ) +} + +export const reduceBy = curry(reduceByFn) diff --git a/src/values.js b/src/values.js index fa6cd843b..e523d01d3 100644 --- a/src/values.js +++ b/src/values.js @@ -1,7 +1,5 @@ import { type } from './type.js' export function values(obj){ - if (type(obj) !== 'Object') return [] - return Object.values(obj) }