https://github.com/streamich/modern-pick
Template string accessors to the selector rescue
https://github.com/streamich/modern-pick
Last synced: 10 months ago
JSON representation
Template string accessors to the selector rescue
- Host: GitHub
- URL: https://github.com/streamich/modern-pick
- Owner: streamich
- License: unlicense
- Created: 2019-01-01T19:43:00.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-12-15T02:28:44.000Z (over 2 years ago)
- Last Synced: 2025-07-04T10:07:23.512Z (12 months ago)
- Language: TypeScript
- Homepage:
- Size: 1.76 MB
- Stars: 11
- Watchers: 1
- Forks: 0
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# modern-pick
Modern selector/picker library utilizing JavaScript template literals.
```js
const data = {
weather: {
data: {
days: [{
conditions: {temperatuer: 26}
}]
}
}
});
pick`weather.data.days[0].conditions.temperature`()(data);
// 👉 26
```
Let's say you have a normalized Redux store.
```js
{
users: {
byId: {
// 1: {}
// 2: {}
// 3: {}
}
}
}
```
And you want to select all users aged over 18.
```js
const getUsersOver18 = pick`users.byId${({age}) => age > 18}`();
```
Let's make the age threshold variable.
```js
const getUsersOver = pick`users.byId${({age}) => over => u.age > over}`;
const getUsersOver18 = getUsersOver(18);
```
Let's limit the number of users to only first five.
```js
const getUsersOver = pick`users.byId${u => over => u.age > over}${'0:5'}`;
```
Let's select only `id` and `name` fields.
```js
const getUsersOver = pick`users.byId${u => over => u.age > over}${'0:5'}->{id,name}`;
```
Let's instead select only the last user and reformat our query to make it look smart.
```js
const getUsersOver = pick`
users.byId
${u => over => u.age > over}
${'-1:'}
->{id,name}
`;
```
Let's break it down.
- `users.byId` — this is an *accessor*, it is compiled to `state = state.users.byId`.
- `${u => over => u.age > over}` — this *filter* expression is compiled to `state = state.filter(u => u.age > over)`.
- `${'-1:'}` — this is a range expression in `start:end:step` format, it is compiled internally to a *filter*, too.
- `->` — *map* operator `->` tells us to do `state = state.map(...)` over the result set.
- `{id,name}` — *destructuring accessor* is internally compiled to `state = (({id, name}) => ({id, name})(state)`.
All-in-all the above query is compiled to a JavaScript function like this:
```js
const getUsersOver = (over) => (state, def) => {
try {
state = state.users.byId;
state = Object.values(state);
state = state.filter(u => u.age > over);
state = state.filter((_, i) => i === state.length - 1);
state = state.map(({id, name}) => ({id, name}));
return state;
} catch {
return def;
}
};
```
## Usage
Install.
```shell
npm i modern-pick
```
Import.
```js
import {id, idx, pick} from 'modern-pick';
```
## Reference
- [`id`](./docs/id.md) — identity function
- [`idx`](./docs/idx.md) — basic accessors
- [`pick`](./docs/pick.md) — pimped accessors
## License
[Unlicense](LICENSE) — public domain.