Functional Programming in JavaScript (IV): Implementing Method Chaining with OOP

Topics

  • Functional Programming in JavaScript
  • Building a Modern JavaScript Library with Vite
  • Unit Testing with Jest and Vitest

Resources

Workshop

Example of method chaining

Implementations in defferent languages:

1
2
3
4
collect([1, 2, 3])
.map((v: number) => v * 2)
.filter((v: number) => v < 5)
.toArray();

Create test case for “map” function

Create an index.test.ts file in src folder.

1
2
3
4
5
6
7
8
9
10
11
import { test, expect } from 'vitest';
import { collect } from './index';

test('map should work', () => {
const actual = collect([1, 2, 3, 4, 5])
.map((v: number) => v * 2)
.toArray();
const expected = [2, 4, 6, 8, 10];

expect(actual).toStrictEqual(expected);
});

Run test command.

1
2
3
4
npm run test

🔴 FAIL src/index.test.ts > method chaining
TypeError: collect is not a function

Implement “map” function

Update index.ts file in src folder, and create a Collection class.

1
2
3
4
5
6
7
class Collection {
private items;

constructor(items: Array<any> = []) {
this.items = items;
}
}

Implement a map function for the class, and return the class itself.

1
2
3
4
5
6
7
8
9
10
11
12
import {
map,
} from './modules';

class Collection {
// ...

map(callable: Function) {
this.items = map(this.items, callable);
return this;
}
}

Implement a toArray function for the class, and return the array data.

1
2
3
4
5
6
7
class Collection {
// ...

toArray() {
return this.items;
}
}

Create a collect helper function, and return a Collection instance.

1
2
3
4
5
6
7
// ...

const collect = (items: Array<any>): Collection => new Collection(items);

export {
collect,
};

Run test command.

1
2
3
npm run test

🟢 PASS Waiting for file changes...

Implement more functions

Implement more functions for the class with TDD:

  • map ✅
  • every
  • filter
  • find
  • forEach
  • includes
  • reduce
  • reject
  • size
  • some

Finally, run coverage command.

1
npm run coverage

Publish to NPM

Build the package before publishing.

1
npm run build

Login to NPM.

1
npm login

Update package.json file.

1
2
3
4
5
6
{
"name": "@username/collection-js",
"private": false,
"version": "1.1.0",
// ...
}

Publish to NPM with dry run.

1
npm publish --dry-run

Publish to NPM.

1
npm publish --access=public

Use package

Try with UMD module

Update index.html file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<!-- ... -->
<body>
<div id="app"></div>
<script src="https://unpkg.com/@username/collection-js"></script>
<script>
const res = window.CollectionJS.collect([1, 2, 3, 4, 5])
.map((v) => v * 2)
.toArray();

console.log(res);
</script>
</body>
</html>

Try with ES module

Install dependencies.

1
npm install @memochou1993/collection-js@latest

Update index.html file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<!-- ... -->
<body>
<div id="app"></div>
<script type="module">
import { collect } from '@memochou1993/collection-js';

const res = collect([1, 2, 3, 4, 5])
.map((v) => v * 2)
.toArray();

console.log(res);
</script>
</body>
</html>

Start a server.

1
npm run dev

Source Code