Advertisement
briank

SolidJS createSingle TypeScript V2

Jan 20th, 2023 (edited)
543
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * createSingle is a "sugar" wrapper around the SolidJS function createSignal:
  3.  * const single = createSingle(value, options?);
  4.  * single (and single.s!) return the original setter, augmented with .g, .s, .r, and .w.
  5.  * single.g (and single.g.g!) return the original getter, augmented with .g and .r, for
  6.  * passing read-only access to other places ("segmentation of access").
  7.  * single.r, single.g.r, and single.g() return the read-only value by calling the getter.
  8.  * single.w = value, single(value), and single.s(value) change the value by calling the setter.
  9.  * single.w also works for read-modify-write (++, --, and op=) but you should use .r otherwise.
  10.  * Notes: single is the *setter*, so single() is not a valid call signature.
  11.  */
  12. import { createSignal, Accessor, Setter } from "solid-js";
  13. export type SignalOptions<T> = { equals?: false | ((prev: T, next: T) => boolean) };
  14.  
  15. type ReaderPrototype<T> = {
  16.   (): T;
  17.   get g (): SingleReader<T>;
  18.   get r (): T;
  19. };
  20. export type SingleReader<T> = Accessor<T> & ReaderPrototype<T>;
  21. type AccessorPrototype<T> = {
  22.   (newv: T): T;
  23.   get g (): SingleReader<T>;
  24.   get r (): T;
  25.   get s (): SingleAccessor<T>;
  26.   get w (): T;
  27.   set w (newv: T);
  28. };
  29. export type SingleAccessor<T> = Setter<T> & AccessorPrototype<T>;
  30. export type CreateSingle<T> = {
  31.   (iv: T, options?: SignalOptions<T>): SingleAccessor<T>;
  32.   accessorPrototype: AccessorPrototype<T>;
  33.   readerPrototype: ReaderPrototype<T>;
  34. };
  35.  
  36. export default function createSingle<T> (iv: T, options?: SignalOptions<T>): SingleAccessor<T> {
  37.   const cs = createSingle as CreateSingle<T>;
  38.  
  39.   if (!cs.readerPrototype) cs.readerPrototype = Object.setPrototypeOf({
  40.     get g () { return this; },
  41.     get r () { return this(); }
  42.   }, Function.prototype) as ReaderPrototype<T>;
  43.  
  44.   if (!cs.accessorPrototype) cs.accessorPrototype = Object.setPrototypeOf({
  45.     get r () { return this.g(); },
  46.     get w () { return this.g(); },
  47.     set w (newv: T) { this(newv); }
  48.   }, Function.prototype) as AccessorPrototype<T>;
  49.  
  50.   const [getter, setter] = createSignal(iv, options);
  51.   // eslint-disable-next-line
  52.   if (!('r' in getter)) Object.setPrototypeOf(getter, cs.readerPrototype);
  53.   if (!('w' in setter)) Object.setPrototypeOf(setter, cs.accessorPrototype);
  54.   if (!('g' in setter)) Object.defineProperty(setter, 'g', { value: getter, writable: false });
  55.   return setter as SingleAccessor<T>;
  56. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement