No description
This repository has been archived on 2023-05-29. You can view files and clone it, but cannot push or open issues or pull requests.
Find a file
2022-04-01 10:00:29 +02:00
.github Add dependabot configuration 2022-03-17 16:41:32 +01:00
.vscode 🎉 Initial commit 2020-07-03 18:01:45 +02:00
src Add exercice on sequence 2022-03-07 15:00:59 +01:00
.eslintrc.js 🎉 Initial commit 2020-07-03 18:01:45 +02:00
.gitignore 🎉 Initial commit 2020-07-03 18:01:45 +02:00
.nvmrc ⬆️ Upgrade all dependencies 2022-01-11 14:47:57 +01:00
.prettierrc 🎉 Initial commit 2020-07-03 18:01:45 +02:00
jest.config.js Stop failing test because of typescript errors 2022-03-04 11:40:00 +01:00
package.json Bump @types/node from 17.0.21 to 17.0.22 2022-03-22 05:29:10 +00:00
README.md Update wording 2022-04-01 10:00:29 +02:00
tsconfig.json 🎉 Initial commit 2020-07-03 18:01:45 +02:00
yarn.lock Bump @types/node from 17.0.21 to 17.0.22 2022-03-22 05:29:10 +00:00

Inato fp-ts training

This repo is a work in progress toward having a comprehensive training material to onboard people on using fp-ts efficiently.

The exercices consist of unimplemented functions and their associated failing tests.

To run the tests, simply run

$ yarn test

You can also run them in watch mode:

$ yarn test:watch

Finally, if you wish to only run the tests for a given exercice exoN, you can run the following:

$ yarn test[:watch] exoN

The exercices are organized into exoN folders and most of what is required to complete each is detailed in the comments.

code style guide

  • Use flow instead of pipe when possible
// Bad
const myFunc = (user: User) => pipe(user, getUserName, formatUserName);

// Good
const myFunc = flow(getUserName, formatUserName);
  • Avoid using boolean method match when unecessary

    Why? boolean.match can lower the global understanding of a method and enforce nested pipes. Using classic if/else is often the best option

// Bad
const myFunc = (condition: boolean) => pipe(
  condition === true,
  boolean.match(
    () => doSomethingOnFalse(...),
    () => doSomethingOnTrue(...)
  )
);

// Good
const myFunc = (condition: boolean) => {
  if (condition === true) {
    return doSomethingOnTrue(...);
  }
  return doSomethingOnFalse(...);
};
  • Split piping from logical actions

    Why? Mixing them makes it harder to understand and read the code. We want to favor the usage of atomic methods that do not know anything about the piping

// Bad
const myFunc = () => pipe(
  rte.Do,
  rte.bind('aggregate', () => getAggregateById(...)),
  rte.bindW(...),
  ...,
  rte.chainW(({ aggregate }) => pipe(
    aggregate.something,
    doSomething,
    doSomethingElse,
    ...
    )
  ),
  rte.chainW(storeAggregate),
);

// Good
const myFunc = () => pipe(
  rte.Do,
  rte.bind('aggregate', () => getAggregateById(...)),
  rte.bindW(...),
  ...,
  rte.chainW(doEverything),
  rte.chainW(storeAggregate),
);

// Best
const buildProps = (...) => pipe(
  rte.Do,
  rte.bind('aggregate', () => getAggregateById(...)),
  rte.bindW(...),
  ...
);
const myFunc = () => pipe(
  buildProps(...),
  rte.chainW(doEverything),
  rte.chainW(storeAggregate),
);