# typed-selector

> A simple, type-safe selector library.

Latest version **0.3.0** (published 2023-07-25) · MIT license · 0 weekly downloads

## Install

```sh
npm install typed-selector
pnpm add typed-selector
yarn add typed-selector
bun add typed-selector
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.3.0 |
| Published | 2023-07-25 |
| First published | 2023-07-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 12.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | mavia |
| Keywords | typescript, functional, redux, select, selector, object, styled-components |

## Links

- npm: https://www.npmjs.com/package/typed-selector
- Repository: https://github.com/LaMavia/typed-selector
- Homepage: https://github.com/LaMavia/typed-selector#readme
- Issues: https://github.com/LaMavia/typed-selector/issues
- npm.io page: https://npm.io/package/typed-selector

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 0.3.0 (latest) — 2023-07-25
- 0.2.3 — 2023-07-24
- 0.2.2 — 2023-07-24
- 0.2.1 — 2023-07-24
- 0.2.0 — 2023-07-24
- 0.1.0 — 2023-07-23

## README

# Typed-Selector

A simple, type-safe selector library.

[![cov](https://raw.githubusercontent.com/LaMavia/typed-selector/gh-pages/badges/coverage.svg)](https://github.com/LaMavia/typed-selector/actions)

Typed-selector exposes 3 types of selectors:

1. proxy selector ([makeSelector](#proxy-selector)) - the most ergonomic, yet the most expensive one;
1. simple path selector ([makePathSelector](#simple-path-selector)) - the cheapest but the least expressive one;
1. class-based path selector ([PathSelector](#class-based-path-selector)) - cheaper than proxy selector, and nearly as expressive.

## Proxy selector

Utilizes immutable proxies together with virtual properties to map object accesses to key fragments used is the final selector.

### Usage

Let us define a state of `State` as

```ts
interface State {
  a: number
  b: {
    a: string
    b: boolean[]
  }
}
```

You can later use `makeSelector` to define a custom selector:

```ts
import { makeSelector } from 'typed-selector'

// equivalent to: state => state
const $ = makeSelector<State>()

// state => state.a
$.a
// state => state.b.a
$.b.a
// state => state.b.b[0]
$.b.b[0]
```

Selectors can be saved at any point, and later extended:

```ts
const $ = makeSelector<State>()
const b$ = $.b.b
const b$first = b$[0]
```

## Simple path selector

Uses dot-separated key paths to make selectors. It's less expensive than `makeSelector` but also less expressive as it doesn't allow for prefixing. The path argument is strongly typed, and supports intellisense. The fragment separator is fixed at `'.'`. To use a custom separator, use `PathSelector` instead.

### Usage

```ts
import { makePathSelector } from 'typed-selector'

interface State {
  root: {
    files: {}
    dirs: {
      projects: {
        files: {}
        dirs: {
          'typed-selector': {
            files: {
              index: string
            }
            dirs: {}
          }
        }
      }
    }
  }
}

const $ = makePathSelector<State>()

const indexSelector: (state: State) => string = $(
  'root.dirs.projects.dirs.typed-selector.files.index'
)
```

## Class-based path selector

Uses immutable classes in combination with string paths. Allows for custom fragment separators, and prefixing.

### Constructors

`PathSelector` doesn't expose its raw constructor but exposes two factory functions:

1. `make(options)` - accepts all the options at once but setting a custom separator requires duplicating it as the second type parameter. All possible options are defined in `PathSelectorOptions`. For example:
   ```ts
   PathSelector.make<typeof state, '/'>({ separator: '/' })
   ```
1. `empty()` - creates a default PathSelector instance, using `'.'` as the separator. The separator can later be changed with `separator(newSeparator)`. For example:
   ```ts
   PathSelector.empty<typeof state>()
   // or with a custom separator
   PathSelector.empty<typeof state>().separator('/')
   ```

### Usage

```ts
import { PathSelector } from 'typed-selector'

interface State {
  a: number
  b: {
    a: string
    b: boolean[]
  }
}

declare const state: State

const $ = PathSelector.empty<State>()
const b$ = $.then('b')
// b: { a: string
//    , b: boolean[]
//    }
const b = b$.select(state)
const bArr$first = b$.separator('&').then('b&0')
```

## Examples

### styled-components theme selector

Let us define the theme as

```ts
interface DefaultTheme {
  fontSize: {
    large: string
    small: string
  }
  pallette: {
    primary: {
      text: string
      background: string
    }
    secondary: {
      text: string
      background: string
    }
  }
}
```

Later define the selector `$theme` as

```ts
import { ThemeProps } from 'styled-components'
import { makeSelector } from 'select'

const $theme = makeSelector<{ theme: DefaultTheme }>().theme
```

It can then be used as follows:

```ts
import { styled } from 'styled-components'

const $primary = $theme.pallette.primary

const StyledDiv = styled.div`
  font-size: ${$theme.fontSize.small};
  color: ${$primary.text};
  background-color: ${$primary.background};
`
```

---
_Source: https://npm.io/package/typed-selector · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
