README
Tsfunct is a TypeScript functional library made directly with and for TS with its static typesystem in mind.
Installation
To install this package run either:
yarn add @siegrift/tsfunct
or if you use npm
npm i @siegrift/tsfunct --save
Important: Some functions (set and friends) work reliably only with TS ^3.7, because of this issue. Also, this library will be using latest TS features when needed. Keep this in mind if you are trying to use it in your project.
API and documentation
Documentation is automatically generated from source code and can be found at github pages here.
You can also play with the library on CodeSandbox.
You can read the list and sources of all helpers in the src/lib folder here.
Motivation
There are two big libraries which provide helper functions for JS/TS. These are lodash and ramda. Both of these libraries are made for JS and the TS typings for many functions are poor. Also, these functions aim to be as general as possible, which makes it harder or even impossible to type properly.
There are certain helpers (mainly for immutable object manipulation) which can be typed better.
Let's take a look at get(obj, path)
helper in both lodash (4.14.132) and ramda (0.26.9),
when using it on a strongly typed TS object.
(Lodash gets it at least correct, but cannot
determine the result type. Ramda allows you to pass a type that is being returned, but you can omit
it and produce incorrect result type)
(There are no TS warnings about accessing
value on nonexistent path)
Lets look what you can get by using get(obj, path)
with TSfunct.
There are many advantages of this
helper:
- The result has correct type
- The path can be autocompleted and must be able to exist in the object
- Handles arrays, optional and nullable values (even in intermediate objects)
When you call update for the first time, value
in
update function can be undefined
(if any intermediate value doesn't exist). However, when calling
it for a second time, it is guaranteed that the values on the path exist.
Refer to documentation, source code and tests for more examples.
Immutability
All functions in this library are effectively immutable. That means that if you use the helpers according to their idiomatic usage, library is immutable. However, there are no deep copies created for the source values and you are able to modify the original entity if you try really hard.
const original = [{ a: 0 }, { a: 1 }, { a: 2 }]
const mapped = map(original, (val) => (val.a = 3))
// 'mapped' will equal to [3, 3, 3]
// 'original' will equal to [{ a: 3 }, { a: 3 }, { a: 3 }]
Chaining
TLDR: It is a bad idea. If you want to learn more, read this article
Functional programming style
Most of the functions in this library are written imperatively (e.g. const get = (object, path) => implementation
compared to traditional functional const get = (path) => (object) => implementation
) for better typing and autocompletion support. These helpers aren't composable
together and if you would like to do multiple transformations you would have to either nest the
calls (which hurts readability) or introduce unnecessary local variables.
For this reason, there are also functional alternatives of most common methods (in the future
maybe all of them), which offer the same type guarantees and their imperative clones. These fp
helpers have prefix fp
(e.g. functional version of set
helper is called fpSet
).
(If you are looking for more FP helpers have a look at monocle or fp ts or lodash fp)
Codebase overview
Each helper is written in its own module without depending on other helper. This allows you to copy the source of single helper you want without installing the whole library.
Limitations
Most of the helpers are typed manually and have some restrictions on its arguments. For example, path array can be up to X elements only in some helpers...
Bear in mind that TS is unsound! Types might easily lie to you if you are not careful. For example,
const arr: number[] = [1, 2, 3]
const num: number = get(arr, [999]) // this line won't trigger TS error!
console.log(num) // undefined!
Other limitation is for example TS path autocompletion for immutability helpers, which I reported and is tracked in this issue and will be fixed in the future.
Issues
Each helper is heavily tested and I try to make the library as stable as possible. In case there is a bug or unwanted behavior, please create an issue.
Contribution
If you would like to fix an issue or create another helper, feel free to create a PR for it. To contribute just follow these steps:
- fork the repository
- make sure you have yarn installed and run:
yarn
- create a new branch with you feature
- commit & push
- create PR to the original repo