Skip to content

Commit 22f68df

Browse files
committed
Initial v3 implementation
1 parent d586519 commit 22f68df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+3406
-1091
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ playground/
1919

2020
*.bs.js
2121
*.gen.tsx
22+
23+
./src/**/index.ts

.prettierrc

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"semi": false,
44
"singleQuote": true,
55
"trailingComma": "all",
6-
"printWidth": 100,
7-
"arrowParens": "avoid"
6+
"arrowParens": "avoid",
7+
"printWidth": 100
88
}

README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@
2929

3030
## Features
3131

32+
- better type inference because of the `data-first` implementation
33+
- built on top of ReScript (interesting combination, isn't it?), which automatically generates most of TS signatures and performant JS code
34+
35+
- benchmark results are various, but in general `ts-belt` always takes either the first or second place (remeda/rambda/ramda/lodash-fp), and especially comparing to `remeda`, which also follows the `data-first` approach, `ts-belt` is much faster, you can find the benchmarks results here
36+
- `ts-belt` provides `Option` and `Result` implementation instead of `null` and `undefined` (get rid of them in your project!)
37+
- high tests coverage
38+
- lightweight, no external dependencies
39+
- tree-shakeable
40+
- fully documented
41+
3242
- [lightweight](https://bundlephobia.com/result?p=@mobily/ts-belt), no dependencies
3343
- type safety, full TypeScript support
3444
- high tests coverage
@@ -49,7 +59,7 @@ npm install @mobily/ts-belt --save
4959

5060
## Api Reference
5161

52-
Full documentation is available [here](https://mobily.github.io/ts-belt/).
62+
Full documentation can be found [here](https://mobily.github.io/ts-belt/).
5363

5464
## Contributors
5565

__tests__/Array/deepFlat.test.ts

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { expectType } from 'ts-expect'
2+
3+
import { A, pipe } from '../..'
4+
5+
describe('deepFlat', () => {
6+
it('provides correct types', () => {
7+
expectType<ReadonlyArray<number>>(A.deepFlat([1, 2, 3, 4, 5]))
8+
expectType<ReadonlyArray<number>>(A.deepFlat([[1, 2], 3, [4, 5]]))
9+
expectType<ReadonlyArray<number>>(
10+
A.deepFlat([
11+
[1, 2],
12+
[[3], [4, 5]],
13+
]),
14+
)
15+
expectType<ReadonlyArray<number | string>>(
16+
A.deepFlat([
17+
[1, 2],
18+
[[3], ['hello', 'world']],
19+
]),
20+
)
21+
})
22+
23+
it('flattens an array correctly', () => {
24+
const result = A.deepFlat([[1, 2], 3, [4, 5]])
25+
expect(result).toEqual([1, 2, 3, 4, 5])
26+
})
27+
28+
it('flattens nested arrays', () => {
29+
const result = A.deepFlat([
30+
[1, 2],
31+
[[3], [4, 5]],
32+
])
33+
expect(result).toEqual([1, 2, 3, 4, 5])
34+
})
35+
36+
it('flattens a single value', () => {
37+
const result = A.deepFlat([[1]])
38+
expect(result).toEqual([1])
39+
})
40+
})
41+
42+
describe('deepFlat (pipe)', () => {
43+
it('provides correct types', () => {
44+
expectType<ReadonlyArray<number>>(pipe([1, 2, 3, 4, 5], A.deepFlat))
45+
expectType<ReadonlyArray<number>>(pipe([[1, 2], 3, [4, 5]], A.deepFlat))
46+
expectType<ReadonlyArray<number>>(
47+
pipe(
48+
[
49+
[1, 2],
50+
[[3], [4, 5]],
51+
],
52+
A.deepFlat,
53+
),
54+
)
55+
expectType<ReadonlyArray<number | string>>(
56+
pipe(
57+
[
58+
[1, 2],
59+
[[3], ['hello', 'world']],
60+
],
61+
A.deepFlat,
62+
),
63+
)
64+
})
65+
66+
it('flattens an array correctly', () => {
67+
const result = pipe([[1, 2], 3, [4, 5]], A.deepFlat)
68+
expect(result).toEqual([1, 2, 3, 4, 5])
69+
})
70+
71+
it('flattens nested arrays', () => {
72+
const result = pipe(
73+
[
74+
[1, 2],
75+
[[3], [4, 5]],
76+
],
77+
A.deepFlat,
78+
)
79+
expect(result).toEqual([1, 2, 3, 4, 5])
80+
})
81+
82+
it('flattens a single value', () => {
83+
const result = pipe([[1]], A.deepFlat)
84+
expect(result).toEqual([1])
85+
})
86+
})

__tests__/Array/drop.test.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import { A } from '../..'
22

33
describe('drop', () => {
44
it('should return the same values as the provided array', () => {
5-
expect(A.drop(-1, [1, 2, 3])).toEqual([1, 2, 3])
5+
expect(A.drop([1, 2, 3], -1)).toEqual([1, 2, 3])
66
})
77

88
it('should return an empty array', () => {
9-
expect(A.drop(4, [1, 2, 3])).toEqual([])
10-
expect(A.drop(3, [1, 2, 3])).toEqual([])
9+
expect(A.drop([1, 2, 3], 4)).toEqual([])
10+
expect(A.drop([1, 2, 3], 3)).toEqual([])
1111
})
1212

1313
it('should return a new array that does not contain the first `n` items', () => {
14-
expect(A.drop(0, [])).toEqual([])
15-
expect(A.drop(0, [1, 2, 3])).toEqual([1, 2, 3])
16-
expect(A.drop(1, [1])).toEqual([])
17-
expect(A.drop(1, [1, 2, 3])).toEqual([2, 3])
18-
expect(A.drop(1, [[1], [2]])).toEqual([[2]])
19-
expect(A.drop(2, [true, true, false])).toEqual([false])
14+
expect(A.drop([], 0)).toEqual([])
15+
expect(A.drop([1, 2, 3], 0)).toEqual([1, 2, 3])
16+
expect(A.drop([1], 1)).toEqual([])
17+
expect(A.drop([1, 2, 3], 1)).toEqual([2, 3])
18+
expect(A.drop([[1], [2]], 1)).toEqual([[2]])
19+
expect(A.drop([true, true, false], 2)).toEqual([false])
2020
})
2121
})

__tests__/Array/flat.test.ts

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { expectType } from 'ts-expect'
2+
3+
import { A, pipe } from '../..'
4+
5+
describe('flat', () => {
6+
// it('provides correct types', () => {
7+
// expectType<ReadonlyArray<number>>(A.flat([1, 2, 3, 4, 5]))
8+
// expectType<ReadonlyArray<number>>(A.flat([[1, 2], 3, [4, 5]]))
9+
// expectType<ReadonlyArray<number>>(
10+
// A.flat([
11+
// [1, 2],
12+
// [[3], [4, 5]],
13+
// ]),
14+
// )
15+
// expectType<ReadonlyArray<(number | string | number[])[]>>(
16+
// A.flat([
17+
// [1, 2],
18+
// [[3], ['hello', 'world']],
19+
// ]),
20+
// )
21+
// })
22+
23+
it('flattens an array correctly', () => {
24+
const result = A.flat([[1, 2], 3, [4, 5]])
25+
expect(result).toEqual([1, 2, 3, 4, 5])
26+
})
27+
28+
it('flattens nested arrays', () => {
29+
const result = A.flat([
30+
[1, 2],
31+
[[3], [4, 5]],
32+
])
33+
expect(result).toEqual([1, 2, [3], [4, 5]])
34+
})
35+
36+
it('flattens a single value', () => {
37+
const result = A.flat([[1]])
38+
expect(result).toEqual([1])
39+
})
40+
})
41+
42+
describe('flat (pipe)', () => {
43+
// it('provides correct types', () => {
44+
// expectType<ReadonlyArray<number>>(pipe([1, 2, 3, 4, 5], A.flat))
45+
// expectType<ReadonlyArray<number>>(pipe([[1, 2], 3, [4, 5]], A.flat))
46+
// expectType<ReadonlyArray<number>>(
47+
// pipe(
48+
// [
49+
// [1, 2],
50+
// [[3], [4, 5]],
51+
// ],
52+
// A.flat,
53+
// ),
54+
// )
55+
// expectType<ReadonlyArray<number | string>>(
56+
// pipe(
57+
// [
58+
// [1, 2],
59+
// [[3], ['hello', 'world']],
60+
// ],
61+
// A.flat,
62+
// ),
63+
// )
64+
// })
65+
66+
it('flattens an array correctly', () => {
67+
const result = pipe([[1, 2], 3, [4, 5]], A.flat)
68+
expect(result).toEqual([1, 2, 3, 4, 5])
69+
})
70+
71+
it('flattens nested arrays', () => {
72+
const result = pipe(
73+
[
74+
[1, 2],
75+
[[3], [4, 5]],
76+
],
77+
A.flat,
78+
)
79+
expect(result).toEqual([1, 2, [3], [4, 5]])
80+
})
81+
82+
it('flattens a single value', () => {
83+
const result = pipe([[1]], A.flat)
84+
expect(result).toEqual([1])
85+
})
86+
})

__tests__/Array/get.test.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { A } from '../..'
22

33
describe('get', () => {
44
it('should return None', () => {
5-
expect(A.get(0, [])).toBeNone()
6-
expect(A.get(3, [1, 2, 3])).toBeNone()
5+
expect(A.get([], 0)).toBeNone()
6+
expect(A.get([1, 2, 3], 3)).toBeNone()
77
})
88

99
it('should return Some', () => {
10-
expect(A.get(0, [1, 2, 3])).toBeSome(1)
11-
expect(A.get(0, [0, 2, 3])).toBeSome(0)
12-
expect(A.get(2, [true, true, false])).toBeSome(false)
13-
expect(A.get(1, [[1], [2]])).toBeSome([2])
10+
expect(A.get([1, 2, 3], 0)).toBeSome(1)
11+
expect(A.get([0, 2, 3], 0)).toBeSome(0)
12+
expect(A.get([true, true, false], 2)).toBeSome(false)
13+
expect(A.get([[1], [2]], 1)).toBeSome([2])
1414
})
1515
})

__tests__/Array/getBy.test.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import { A } from '../..'
22

33
describe('getBy', () => {
44
it('should return None', () => {
5-
expect(A.getBy(n => n === 0, [1, 2, 3])).toBeNone()
6-
expect(A.getBy(state => state, [false, false, false])).toBeNone()
5+
expect(A.getBy([1, 2, 3], n => n === 0)).toBeNone()
6+
expect(A.getBy([false, false, false], state => state)).toBeNone()
77
expect(
8-
A.getBy(obj => Boolean(obj.prop), [{ prop: null }, { prop: false }, { prop: undefined }]),
8+
A.getBy([{ prop: null }, { prop: false }, { prop: undefined }], obj => Boolean(obj.prop)),
99
).toBeNone()
1010
})
1111

1212
it('should return Some', () => {
13-
expect(A.getBy(str => str.length === 2, ['a', 'ab', 'bc'])).toBeSome('ab')
14-
expect(A.getBy(value => value === 2, [1, 2, 3])).toBeSome(2)
13+
expect(A.getBy(['a', 'ab', 'bc'], str => str.length === 2)).toBeSome('ab')
14+
expect(A.getBy([1, 2, 3], value => value === 2)).toBeSome(2)
1515
expect(
16-
A.getBy(obj => obj.prop.length > 2, [{ prop: 'ab' }, { prop: 'abc' }, { prop: 'bcd' }]),
16+
A.getBy([{ prop: 'ab' }, { prop: 'abc' }, { prop: 'bcd' }], obj => obj.prop.length > 2),
1717
).toBeSome({ prop: 'abc' })
1818
})
1919
})

__tests__/Array/splitAt.test.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import { A } from '../..'
22

33
describe('splitAt', () => {
44
it('should return None', () => {
5-
expect(A.splitAt(1, [])).toBeNone()
6-
expect(A.splitAt(-1, [1, 2, 3])).toBeNone()
7-
expect(A.splitAt(4, [1, 2, 3])).toBeNone()
5+
expect(A.splitAt([], 1)).toBeNone()
6+
expect(A.splitAt([1, 2, 3], -1)).toBeNone()
7+
expect(A.splitAt([1, 2, 3], 4)).toBeNone()
88
})
99

1010
it('should return Some', () => {
11-
expect(A.splitAt(0, [])).toBeSome([[], []])
12-
expect(A.splitAt(1, [1])).toBeSome([[1], []])
13-
expect(A.splitAt(1, [1, 2])).toBeSome([[1], [2]])
14-
expect(A.splitAt(2, [true, true, false])).toBeSome([[true, true], [false]])
15-
expect(A.splitAt(2, [[1], [2], [3], [4]])).toBeSome([
11+
expect(A.splitAt([], 0)).toBeSome([[], []])
12+
expect(A.splitAt([1], 1)).toBeSome([[1], []])
13+
expect(A.splitAt([1, 2], 1)).toBeSome([[1], [2]])
14+
expect(A.splitAt([true, true, false], 2)).toBeSome([[true, true], [false]])
15+
expect(A.splitAt([[1], [2], [3], [4]], 2)).toBeSome([
1616
[[1], [2]],
1717
[[3], [4]],
1818
])

__tests__/Array/take.test.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import { A } from '../..'
22

33
describe('take', () => {
44
it('should return an empty array', () => {
5-
expect(A.take(-1, [1, 2, 3])).toEqual([])
6-
expect(A.take(0, [])).toEqual([])
7-
expect(A.take(0, [1, 2, 3])).toEqual([])
5+
expect(A.take([1, 2, 3], -1)).toEqual([])
6+
expect(A.take([], 0)).toEqual([])
7+
expect(A.take([1, 2, 3], 0)).toEqual([])
88
})
99

1010
it('should return a new array including the first `n` items', () => {
11-
expect(A.take(1, [1])).toEqual([1])
12-
expect(A.take(1, [1, 2, 3])).toEqual([1])
13-
expect(A.take(1, [[1], [2]])).toEqual([[1]])
14-
expect(A.take(2, [true, true, false])).toEqual([true, true])
15-
expect(A.take(3, [1, 2, 3])).toEqual([1, 2, 3])
16-
expect(A.take(4, [1, 2, 3])).toEqual([1, 2, 3])
11+
expect(A.take([1], 1)).toEqual([1])
12+
expect(A.take([1, 2, 3], 1)).toEqual([1])
13+
expect(A.take([[1], [2]], 1)).toEqual([[1]])
14+
expect(A.take([true, true, false], 2)).toEqual([true, true])
15+
expect(A.take([1, 2, 3], 3)).toEqual([1, 2, 3])
16+
expect(A.take([1, 2, 3], 4)).toEqual([1, 2, 3])
1717
})
1818
})

0 commit comments

Comments
 (0)