Common FP
Functional programming for the commoner
What Is It?#
An opinionated utility library with a few goals
- Utilities are built with multiple data types in mind
- Functional without the jargon
- Friendly errors
Get Started#
- Install.sh
npm i common-fp # using typescript? npm i common-fp-types
- And use
import { mapValues } from 'common-fp' const giveEveryoneAnApple = mapValues(numApples => numApples + 1) const applesPerPersonObj = { jason: 2, amy: 3, } const resultObj = giveEveryoneAnApple(applesPerPersonObj) console.log(resultObj) // a new object { // jason: 3, // amy: 4, // }
import { mapValues } from 'common-fp' const giveEveryoneAnApple = mapValues((numApples: number) => numApples + 1) const applesPerPersonObj = { jason: 2, amy: 3, } const resultObj = giveEveryoneAnApple(applesPerPersonObj) console.log(resultObj) // a new object { // jason: 3, // amy: 4, // }
import { mapValues } from 'common-fp' const giveEveryoneAnApple = mapValues( numApples => numApples + 1 ) const applesPerPersonObj = { jason: 2, amy: 3, } const resultObj = giveEveryoneAnApple( applesPerPersonObj ) console.log(resultObj) // a new object { // jason: 3, // amy: 4, // }
import { mapValues } from 'common-fp' const giveEveryoneAnApple = mapValues( (numApples: number) => numApples + 1 ) const applesPerPersonObj = { jason: 2, amy: 3, } const resultObj = giveEveryoneAnApple( applesPerPersonObj ) console.log(resultObj) // a new object { // jason: 3, // amy: 4, // }
You can also pass a Mapconst applesPerPersonMap = new Map([ ['jason', 2], ['amy', 3], ]) const resultMap = giveEveryoneAnApple(applesPerPersonMap) console.log(resultMap) // a new Map [ // ['jason', 3], // ['amy', 4], // ]
const applesPerPersonMap = new Map([ ['jason', 2], ['amy', 3], ]) const resultMap = giveEveryoneAnApple(applesPerPersonMap) console.log(resultMap) // a new Map [ // ['jason', 3], // ['amy', 4], // ]
const applesPerPersonMap = new Map([ ['jason', 2], ['amy', 3], ]) const resultMap = giveEveryoneAnApple( applesPerPersonMap ) console.log(resultMap) // a new Map [ // ['jason', 3], // ['amy', 4], // ]
const applesPerPersonMap = new Map([ ['jason', 2], ['amy', 3], ]) const resultMap = giveEveryoneAnApple( applesPerPersonMap ) console.log(resultMap) // a new Map [ // ['jason', 3], // ['amy', 4], // ]
mapValues works with arrays and Sets as wellconst capitalize = str => str[0].toUpperCase() + str.slice(1) const capitalizeAll = mapValues(capitalize) const peopleArr = ['kim', 'grace'] const resultArr = capitalizeAll(peopleArr) console.log(resultArr) // a new array [ // 'Kim', // 'Grace', // ] const peopleSet = new Set(['kim', 'grace']) const resultSet = capitalizeAll(peopleSet) console.log(resultSet) // a new Set [ // 'Kim', // 'Grace', // ]
const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1) const capitalizeAll = mapValues(capitalize) const peopleArr = ['kim', 'grace'] const resultArr = capitalizeAll(peopleArr) console.log(resultArr) // a new array [ // 'Kim', // 'Grace', // ] const peopleSet = new Set(['kim', 'grace']) const resultSet = capitalizeAll(peopleSet) console.log(resultSet) // a new Set [ // 'Kim', // 'Grace', // ]
const capitalize = str => str[0].toUpperCase() + str.slice(1) const capitalizeAll = mapValues(capitalize) const peopleArr = ['kim', 'grace'] const resultArr = capitalizeAll(peopleArr) console.log(resultArr) // a new array [ // 'Kim', // 'Grace', // ] const peopleSet = new Set(['kim', 'grace']) const resultSet = capitalizeAll(peopleSet) console.log(resultSet) // a new Set [ // 'Kim', // 'Grace', // ]
const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1) const capitalizeAll = mapValues(capitalize) const peopleArr = ['kim', 'grace'] const resultArr = capitalizeAll(peopleArr) console.log(resultArr) // a new array [ // 'Kim', // 'Grace', // ] const peopleSet = new Set(['kim', 'grace']) const resultSet = capitalizeAll(peopleSet) console.log(resultSet) // a new Set [ // 'Kim', // 'Grace', // ]
Why Build It?#
I wanted a utility library that worked with data types generically. Years ago I built a crude personal version I really liked. Common FP is a refined and expanded version that hopefully others find helpful.
Who Is This For?#
Common FP is for people who
- For example, mapValues allows us to map over the values of an array, object, Map, or Set and return a new instance of the data type passed in.
...but not interested in diving in the deep end.
Helpful concepts like immutability are common in JavaScript and can be used without currying, knowing what an "identity function" is, or learning any theory. Those things may be useful for people wanting to learn them but pose a barrier for those who don't.
- Chaining feels natural until you want to call a function outside the prototype. Then you either need to modify the prototype and account for collisions or use a different approach, such as function composition.
Common FP is intended to be read as well as used. Most JavaScript devs should be able to browse the utilities to understand how they work. My goal is to provide a positive debugging experience.
Who Isn't This For?#
Common FP is not for everyone. You may prefer other libraries if you
- Common FP may feel odd and unnecessary to you. That's fine! Keep writing code in a way that's comfortable for you and your team.
- Common FP is opinionated and will throw errors when you use it in an unintended way. For example, mapValues requires you to pass a function, whereas Lodash provides a default. Calling mapValues without a function doesn't make sense to me; thus, I enforce that convention. This is one opinion of many that won't be shared by everyone - which is okay :)