JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10481
  • Score
    100M100P100Q165116F
  • License ISC

A writable derived store for objects and arrays

Package Exports

  • svelte-keyed
  • svelte-keyed/dist/index.es.js
  • svelte-keyed/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (svelte-keyed) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

svelte-keyed-banner

svelte-keyed

npm version npm downloads license build coverage size

A writable derived store for objects and arrays!

const user = writable({ name: { first: 'Rich', last: 'Harris' } });
const firstName = keyed(user, 'name.first');

$firstName = 'Bryan';

console.log($user); // { name: { first: 'Bryan', last: 'Harris' } };

Installation

$ npm i -D svelte-keyed

Since Svelte automatically bundles all required dependencies, you only need to install this package as a dev dependency with the -D flag.

API

keyed takes a writable object store and a keypath, and returns a writable store whose changes are reflected on the original store.

Properties are accessed with dot notation, and arrays can be indexed with bracket notation.

const email = keyed(settings, 'profiles[0].email');

Nullable parents

If the parent store is nullable, then the child store will also be nullable.

type User = {
  name: {
    first: string;
    last: string;
  };
  relations: {
    partner?: User;
  };
};

const maybeUser = writable<User | undefined>(undefined);
// Writable<string | undefined>
const firstName = keyed(maybeUser, 'name.first');

Nullable properties

Nullable properties are accessed with optional chaining behaviour.

const user = writable(initUser);
// Writable<Name | undefined>
const partnerName = keyed(user, 'relations.partner.name');

TypeScript

keyed infers the return type of the keyed store from the keypath.

const user = writable(initUser);
// Writable<string>
const firstName = keyed(user, 'name.first');

keyed will also try to guess all possible keypaths up to a depth limit of 3.

keyed(user, '...');
            ┌───────────────────────────────┐
            │ • name                        │
            │ • name.first                  │
            │ • name.last                   │
            │ • name                        │
            │ • relations                   │
            │ • relations.partner           │
            │ • relations.partner.name      │
            └───────────────────────────────┘

This limit is due to a TypeScript limitation where structured types must be generated statically. Increasing the depth limit slows down type compilation.

Type hints will not be provided for keypaths with a depth greater than 3 but this does not affect the return type.

const user = writable(user);
// Writable<string | undefined>
const firstName = keyed(user, 'relations.partner.name.first');

Motivations

We usually read and write properties of an object store with auto-subscriptions.

<input bind:value={$name.first}/>

However, auto-subscriptions are isolated to a Svelte component. svelte-keyed aims to solve several common limitations listed below.

Context stores

Often, we want to set a property or element of a store into component context, then allow child components to read / write to the property.

<!-- Settings.svelte -->
<script>
  setContext('profileSettings', keyed(settings, 'profile'));
</script>

<GeneralSettings />
<ProfileSettings />
<!-- ProfileSettings.svelte -->
<script>
  const profileSettings = getContext('profileSettings');
</script>

<input type="text" bind:value={$profileSettings.username} />

Helper functions

One important method to reduce clutter on your component is to extract functionality into external helper functions. svelte-keyed allows you to create derived Writable stores that can be passed into or returned from helper functions.

<!-- Settings.svelte -->
<script>
  const stats = writable({ userClicks: 0, userTaps: 0 });
  const clicks = keyed(stats, 'userClicks');
</script>

<div use:trackClicks={clicks} />
<input use:trackClicks={clicks} />
export const trackClicks = (node, clicks) => {
  const listen = () => {
    clicks.update(($clicks) => $clicks + 1);
  };
  node.addEventListener('click', listen);
  return {
    destroy() {
      node.removeEventListener('click', listen);
    },
  };
};