Skip to content
Alex Fox Gill edited this page Nov 26, 2018 · 17 revisions

This page is written with the convention that A is the "source" type of the selector, Params is the optional parameter type and B is the "target" type


choose

Signature: .choose(predicate: (b: B) => b is C)

Available on: Selector, MaybeSelector

Narrows down a selector to a subtype of B

Example
interface CSV {
  type: 'csv'
  delimiter: string
}
interface Binary {
  type: 'binary'
}
type FileFormat = CSV | Binary
const isCsv = (format: FileFormat): x is CSV => format.type === 'csv'

const csvSelector = fileFormatSelector.choose(isCsv)

combine

Signature: .combine(other: Get<A, C>)

Available on: Get

Merges the results of two Gets


compose

Signature: .compose(other: Transformer<B, C>)

Available on: Selector, MaybeSelector, Converter, MaybeConverter, Get

Composes a transformer from A to B with one from B to C, producing one from A to C.

The type of transformer returned depends on the two input transformers:

Get MaybeSelector Selector MaybeConverter Converter
Get Get Get Get Get Get
MaybeSelector Get MaybeSelector MaybeSelector MaybeSelector MaybeSelector
Selector Get MaybeSelector Selector MaybeSelector Selector
MaybeConverter Get MaybeSelector MaybeSelector MaybeConverter MaybeConverter
Converter Get MaybeSelector Selector MaybeConverter Converter

Selector composition allows you to define selectors locally to a module, then 'globalise' them by composing.

Example
const moduleSelector: Selector<Root, Module> = ...
const localSelector: Selector<Module, Foo> = ...

const globalSelector: Selector<Root, Foo> = moduleSelector.compose(localSelector)

debug

Signature: .debug()

Available on: Selector, MaybeSelector, Converter, MaybeConverter, Get, Set, Modify

Installs the Debug extension that logs to the console during calls to get, set or modify.


deepMerge

Signature:

.deepMerge(a: A, [params: Params, ] partialB: DeepPartial<B>): A
.deepMerge(partialB: DeepPartial<B>): Update<A, Params>

Available on: Selector, MaybeSelector, Modify

Performs a deep merge on the target location, recursively overwriting any properties that are present in the partialB argument. When only the partialB argument is provided, a chainable Update is returned.

Example
interface Root {
  foo: Foo
}
interface Foo {
  bar: {
    value: number
    name: string
  }
  qux: boolean
}

const fooSelector: Selector<Root, Foo> = ...
fooSelector.deepMerge(root, { bar: { value: 2 } })

extend

Signature: .extend(extension: Extension)

Available on: Selector, MaybeSelector, Converter, MaybeConverter, Get, Set, Modify

Returns a new version of the transformer with the given extension installed.


indexBy

Signature: .indexBy(key: string, [defaultValue: C])

Available on: Selector, MaybeSelector

Composes the selector with a MaybeSelector that looks up a value by a key added to the Params object. If defaultValue is given, the MaybeSelector is converted into a Selector with defaultValue returned if the key does not exist.

Example
interface Root {
  foos: Foos
}
type Foos = { [key: string]: number }

const root: Root = {
  foos: {
    "a": 1,
    "b": 2
  }
}

const foosSelector: Selector<Root, Foos> = ...
const fooSelector = foosSelector.indexBy('fooId')

// 2
const b = fooSelector.get(root, { fooId: "b" })

// null
const x = fooSelector.get(root, { fooId: "x" })

get

Signature: .get[(a: A, [params: Params])]

Available on: Selector, MaybeSelector, Converter, MaybeConverter

Returns the Get associated with this transformer. Can be called immediately as a function, or further transformed.

Example
const fooSelector: Selector<Root, Foo> = ...
const fooGet: Get<Root, Foo> = fooSelector.get

fooGet(root) // returns a Foo

map

Signature: .map(mapFn: (B, Params) => C)

Available on: Get

Modifies the value returned by the Get according to a function.

Only available on Get because the inverse operation would need to be supplied for any other transformer, whereas Get only works one-way. If you need a two-way transformation, this is what a Converter does.

Example
const getNumber: Get<Root, number> = ...
const getString: Get<Root, string> = getNumber.map(x => x.toString())

mapParams

Signature: .mapParams<P2>(fn: P2 => Params)

Available on: Selector, MaybeSelector, Get, Set, Modify

Allows the introduction of new parameters by defining a mapping onto the existing ones


memoize

Signature: .memoize()

Available on: Selector, MaybeSelector, Converter, MaybeConverter, Get, Modify

Applies the Memoize extension which performs a reference equality check on the input (and a shallow equality check on the parameters) for the Get part of a selector. Subsequent selectors also have the memoization applied.


merge

Signature:

.merge(a: A, [params: Params, ] partialB: Partial<B>): A
.merge(partialB: Partial<B>): Update<A, Params>

Available on: Selector, MaybeSelector, Modify

Performs a shallow merge on the target location, overwriting properties from partialB. If only partialB is provided, returns a chainable Update.


modify

Signature:

.modify(a: A, [params: Params, ] f: B => B): A
.modify(f: B => B): Update<A, Params>

Available on: Selector, MaybeSelector

Returns a Modify, which applies a given function to the target location. Can be called immediately as a function, or further transformed. If only the modifier function is provided, returns a chainable Update.


prop

Signature: .prop<K extends keyof B>(key: K)

Available on: Selector, MaybeSelector

Returns a new selector targetting the given property

Example
interface Foo {
  bar: Bar
}
interface Bar {
  value: number
}

const barSelector: Selector<Foo, Bar> = ...
const valueSelector = barSelector.prop('value')

set

Signature:

.set(a: A, [params: Params], b: B): A
.set(b: B): Update<A, Params>

Available on: Selector, MaybeSelector

Returns a Set, which updates the object at the target location. Can be called immediately as a function, or further transformed. If only the b parameter is provided, returns a chainable Update.


withDefault

Signature: .withDefault(ifNull: (A, Params) => B)

Available on: MaybeSelector

Converts the MaybeSelector into a Selector by using the given function as a backup if the value at the target location does not exist.


withDefaultValue

Signature: .withDefault(ifNull: B)

Available on: MaybeSelector

Converts the MaybeSelector into a Selector by using the given value as a backup if the value at the target location does not exist.


withParams

Signature: .withParams(params: Partial<Params>)

Available on: Selector, MaybeSelector, Get, Set

Supplies the given parameters to the selector so that they won't subsequently be required.


Chainable Updates

The updater methods .set, .modify, .merge and .deepMerge can all be called with a single parameter, returning an Update<A, Params>. This is a function that can be applied directly or chained to create a series of transformations:

const updated = firstNameSelector.set("Brian")
  .andThen(ageSelector.modify(x => x + 1))
  .applyTo(state, { userId })