Tsfunct
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: This library is using latest TS features when needed. Keep this in mind if you are trying to use it in your project.
API and documentation
Extended documentation can be found at github pages. You can also play with the library on CodeSandbox.
The error handling utilities, go
and goSync
are inspired by
promise-utils library which offers extended
functionality.
You can check the sources of all helpers in the src/lib folder.
Motivation
Most popular libraries providing helper functions for JS and TS are lodash and ramda. Many functions have poor TS typings, often for the added benefit of flexibility.
There are certain helpers (mainly for immutable object manipulation) which can be typed better if
they are designed specifically for TS. 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.
Immutability
All functions in this library are immutable. However, some functions allow you to pass a predicate function. If this function is mutable they will modify the source value as well.
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
Chaining is not supported and it's not a good idea in general. If you want to learn more, read this article
Functional programming style
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.
If you are looking for more FP helpers have a look at monocle or fp ts or lodash fp)
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 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
Publishing
To release a new version follow these steps:
-
git checkout master && git pull
- ensure you are on the "master" branch with latest changes -
yarn version
- choose "x.y.z" as the version to be released -
git show
- verify the changes of the version commit -
yarn build
- only build the package after the "yarn version" command so the bundled "package.json" uses the updated version yarn publish --access public
-
git push --follow-tags
- to push the commits to a "main" branch