1.0.2 • Published 9 months ago

stringify-accessor v1.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

stringify-accessor

Typesafe, runtime stringification of property accessor paths powered by ES6 Proxies

Install

npm i stringify-accessor

Usage

import stringifyAccessor from "stringify-accessor";

interface FormFields {
  name: {
    first: string;
    last: string;
    suffix?: string;
  };
  favoriteColors?: {
    hex: string;
    name: string;
  }[];
}

stringifyAccessor<FormFields>((form) => form.favoriteColors?.[0].hex); //=> favoriteColors[0].hex

Example: Typesafe form input names

import { set } from "lodash";
import stringifyAccessor from "stringify-accessor";

interface FormFields {
  name: {
    first: string;
    last: string;
    suffix?: string;
  };
  favoriteColors?: {
    hex: string;
    name: string;
  }[];
}

export function MyForm() {
  function processForm(
    e: Event & {
      currentTarget: HTMLFormElement;
    }
  ) {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const form = {};

    for (const [key, value] of formData.entries()) {
      set(form, key, value);
    }

    return form as FormFields;
  }
  const favoriteColors: NonNullable<FormFields['favoriteColors']> = [{ hex: "", name: "" }, { hex: "", name: "" }]

  return (
    <form onSubmit={e => {
        const form = processForm(e);
        console.log(form); //=> { name: { first: "", last: "", suffix: "" }, favoriteColors: [{ hex: "", name: "" }, { hex: "", name: "" }] }
    }}>
      <input
        name={stringifyAccessor<FormFields>((form) => form.name.first)}
        type="text"
      />
      <input
        name={stringifyAccessor<FormFields>((form) => form.name.last)}
        type="text"
      />
      <input
        name={stringifyAccessor<FormFields>((form) => form.name?.suffix)}
        type="text"
      />
      <p>List your two favorite colors</p>
      <ul>
          {favoriteColors.map((color, i) => (
              <li>
                  <input
                      name={stringifyAccessor<FormFields>(
                          (form) => form.favoriteColors?.[i].hex
                      )}
                      type="color"
                      value={color.hex}
                  />
                  <input
                      name={stringifyAccessor<FormFields>(
                          (form) => form.favoriteColors?.[i].name
                      )}
                      type="text"
                      value={color.name}
                  />
              </li>
          ))}
      </ul>
      <button type="submit">submit</button>
    </form>
  );
}

Benchmarking

All benchmarks were run on a 2017 Macbook Pro with macOS Ventura 13.6.9, 2.9 GHz Quad-Core Intel Core i7.

Without caching

Operationops/secAverage Time (ns)MarginSamples
3-level property access (full path)585,7161707.31±6.49%5858
3-level property & index access (full path)510,6741958.19±4.44%5107
6-level property access (full path)486,9872053.44±6.89%4870
6-level property & index access (full path)425,2812351.39±6.84%4253
26-level property access (full path)213,6214681.19±6.59%2137
26-level property access (final segment)265,7133763.45±4.16%2658
Mixed index, property, and symbol access306,7233260.27±6.10%3068
Accessing built-in properties (e.g. Window)475,8062101.70±1.10%4759

With caching

The stringifyAccessor function doesn't use caching, but it can be trivially added. There is a reference memoization implementation using Map in memoized.benchmark.ts.

Operationops/secAverage Time (ns)MarginSamples
3-level property access (full path)1,142,291875.4335173602115±0.14%11423
3-level property & index access (full path)1,089,693917.6895313660268±6.64%10897
6-level property access (full path)1,191,401839.3473100922362±0.16%11915
6-level property & index access (full path)1,092,840915.0468961722853±0.14%10929
26-level property access (full path)642,8421555.5921415274688±11.47%6429
26-level property access (final segment)492,5032030.440875780181±0.13%4926
Mixed index, property, and symbol access555,2391801.025442404724±0.13%5553
Accessing built-in properties675,7351479.868724452705±1.84%6758
1.0.2

9 months ago

1.0.1

9 months ago

1.0.0

9 months ago