Spacelift
Functional utils for Arrays, Objects, Maps, Sets.
Install / Use
/learn @AlexGalays/SpaceliftREADME
space-lift "Lift your values into space for infinite possibilities"

Note: Starting from version 1.0.0, space-lift no longer contains the Option and Result monads. You can find these at space-monad
Rich Array, Object, Map, Set wrapper
Design goals
- 100% immutable, no magic, no overwhelming polymorphism or dynamic operators
- Fun to use
- Correctness and first-class typescript typings
- Tiny and performant (
space-liftweights7.2 kBminified for roughly the same scope aslodash(70.0 kB) ANDimmerjs(15.6 kB)) and no amount of tree shaking can save you from heavy abstractions imported by all modules. - Small set of functions, configurable with lambdas
- Cover 95% of frontend data transformation needs without becoming a bloated lib just to cover the remaining 5%

<a name="howtouse"></a>
How to use
Here's everything that can be imported from space-lift:
import {
lift,
update,
range,
is,
createUnion,
createEnum,
identity,
noop,
Result,
Ok,
Err,
Immutable
} from 'space-lift'
liftis the main attraction and is used to wrap an Array, Object, Map or Set to give it extra functionalitiesupdatecan update an Object, Array, Map or Set without modifying the originalrangeis a factory function for Arrays of numbersisis a helper used to determine if an instance is of a particular type (e.gis.array([]) === true)createUnioncreates a bunch of useful things when working with discriminated unions.createEnumcreates a bunch of useful things when working with a string based enum.identitythe identity functionnoopa function that does nothingResult,Ok,Errare used to work with computation that may failImmutablea helper type that will recursively make a treeReadonly.
<a name="examples"></a>
Some Examples
Update an object inside an Array
import { update } from 'space-lift'
const people = [
{ id: 1, name: 'jon' },
{ id: 2, name: 'sarah' },
{ id: 3, name: 'nina' }
]
const updatedPeople = update(people, draft => {
draft.updateIf(
p => p.id === 2,
personDraft => {personDraft.name = 'Nick'})
})
Sort on two fields
import lift from 'space-lift'
const people = [
{ first: 'jon', last: 'haggis' },
{ first: 'sarah', last: 'john' },
{ first: 'nina', last: 'pedro' }
]
// This will create an Array sorted by first name, then by last name
const sortedPeople = lift(people)
.sort(p => p.first, p => p.last)
.value()
<a name="api"></a>
API
<a name="api.array"></a>
Array
- append
- appendAll
- compact
- count
- collect
- distinct
- drop
- dropRight
- filter
- first
- flatMap
- flatten
- reduce
- get
- groupBy
- grouped
- insert
- last
- map
- removeAt
- reverse
- sort
- take
- takeRight
- toSet
- updateAt
- pipe
<a name="array.append"></a>
Array.append
Appends one item at the end of the Array.
import {lift} from 'space-lift'
const updated = lift([1, 2, 3]).append(4).value() // [1, 2, 3, 4]
<a name="array.appendAll"></a>
Array.appendAll
Appends an Iterable of items at the end of the Array.
import {lift} from 'space-lift'
const updated = lift([1, 2, 3]).appendAll([4, 5]).value() // [1, 2, 3, 4, 5]
<a name="array.compact"></a>
Array.compact
Filters all the falsy elements out of this Array.
All occurences of false, null, undefined, 0, "" will be removed.
import {lift} from 'space-lift'
const updated = lift([1, null, 2, 3, undefined]).compact().value() // [1, 2, 3]
<a name="array.count"></a>
Array.count
Counts the items satisfying a predicate.
import {lift} from 'space-lift'
const count = lift([1, 2, 3]).count(n => n > 1) // 2
<a name="array.collect"></a>
Array.collect
Maps this Array's items, unless void or undefined is returned, in which case the item is filtered.
This is effectively a filter + map combined in one.
import {lift} from 'space-lift'
const count = lift([1, 2, 3]).collect(n => {
if (n === 1) return;
return `${n*10}`
}).value() // ['20', '30']
<a name="array.distinct"></a>
Array.distinct
Creates an array without any duplicate item.
If a key function is passed, items will be compared based on the result of that function;
if not, they will be compared using strict equality.
import {lift} from 'space-lift'
const people = [{id: 1, name: 'Alexios'}, {id: 2, name: 'Bob'}, {id: 1, name: 'Alessia'}]
// [{id: 1, name: 'Alexios'}, {id: 2, name: 'Bob'}]
const deduped = lift(people).distinct(p => p.id).value()
<a name="array.drop"></a>
Array.drop
Drops the first 'count' items from this Array.
import {lift} from 'space-lift'
const updated = lift([1, 2, 3]).drop(2).value() // [3]
<a name="array.dropRight"></a>
Array.dropRight
Drops the last 'count' items from this Array.
import {lift} from 'space-lift'
const updated = lift([1, 2, 3]).dropRight(2).value() // [1]
<a name="array.filter"></a>
Array.filter
Filters this array by aplying a predicate to all items and refine its type.
import {lift} from 'space-lift'
const filtered = lift([1, 2, 3]).filter(n => n > 1).value() // [2, 3]
<a name="array.first"></a>
Array.first
Returns the first element in this Array or undefined.
import {lift} from 'space-lift'
const first = lift([1, 2, 3]).first() // 1
<a name="array.flatMap"></a>
Array.flatMap
Maps this Array to an Array of Array | ArrayWrapper using a mapper function then flattens it.
import {lift} from 'space-lift'
const mapped = lift([1, 2, 3]).flatMap(n => [n + 1, n + 2]).value() // [2, 3, 3, 4, 4, 5]
<a name="array.flatten"></a>
Array.flatten
Flattens this Array of Arrays.
import {lift} from 'space-lift'
const flattened = lift([1, [2], [3, 4]]).flatten().value() // [1, 2, 3, 4]
<a name="array.reduce"></a>
Array.reduce
Reduces this Array into a single value, using a starting value.
import {lift} from 'space-lift'
const count = lift([1, 2, 3]).reduce(0, (count, n) => count + n) // 6
<a name="array.get"></a>
Array.get
Returns the item found at the provided index or undefined.
import {lift} from 'space-lift'
const secondItem = lift([1, 2, 3]).get(1) // 2
<a name="array.groupBy"></a>
Array.groupBy
Creates a Map where keys are the results of running each element through a discriminator function.
The corresponding value of each key is an array of the elements responsible for generating the key.
import {lift} from 'space-lift'
const people = [
{ age: 10, name: 'jon' },
{ age: 30, name: 'momo' },
{ age: 10, name: 'kiki' },
{ age: 28, name: 'jesus' },
{ age: 29, name: 'frank' },
{ age: 30, name: 'michel' }
]
// Map<number, Array<{age: number, name: string}>>
const peopleByAge = lift(people).groupBy(p => p.age).value()
<a name="array.grouped"></a>
Array.grouped
Creates a new Array where each sub array contains at most 'bySize' elements.
import {lift} from 'space-lift'
const numbers = [1, 2, 3, 4, 5, 6, 7]
// [[1, 2], [3, 4], [5, 6], [7]]
const groupedNumbers = lift(numbers).grouped(2).value()
<a name="array.insert"></a>
Array.insert
Inserts an item at a specified index.
import {lift} from 'space-lift'
const updated = lift(['1', '2', '3']).insert(1, '20').value() // [1, 20, 2, 3]
<a name="array.last"></a>
Array.last
Returns the item found at the last index or undefined.
import {lift} from 'space-lift'
const last = lift(['1', '2', '3']).last() // '3'
<a name="array.map"></a>
Array.map
Maps this Array using a mapper function.
import {lift} from 'space-lift'
const mapped = lift(['1', '2', '3']).map(str => '0' + str).value() // ['01', '02', '03']
<a name="array.removeAt"></a>
Array.removeAt
Removes the item found at the specified index.
import {lift} from 'space-lift'
const updated = lift(['1', '2', '3']).removeAt(1).value() // ['1', '3']
<a name="array.reverse"></a>
Array.reverse
Reverses the Array.
import {lift} from 'space-lift'
const updated = lift(['1', '2', '3']).reverse().value() // ['3', '2', '1']
<a name="array.sort"></a>
Array.sort
Sorts the Array in ascending order, using one or more iterators specifying which field to compare.
For strings, localCompare is used.
The sort is stable if the browser uses a stable sort (all modern engines do)
import {lift} from 'space-lift'
const people = [
{ name: 'Jesse', creationDate: 2 },
{ name: 'Walt', creationDate: 1 },
{ name: 'Mike', creationDate: 4 },
{ name: 'Skyler', creationDate: 3 }
]
const sorted = lift(people)
.sort(p => p.creationDate)
.map(p => p.name)
.value() // ['Walt', 'Jesse', 'Skyler', '
