npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@typed-f/lens

v0.3.8

Published

[![NPM Version][lens-npm-version-badge]][lens-npm] [repo-circleci-badge]: https://img.shields.io/circleci/project/github/Ailrun/typed-f/master.svg?logo=circleci [![Known Vulnerabilities][lens-snyk-badge]][lens-snyk] [![Supported TypeScript Version][repo-s

Downloads

122

Readme

@typed-f/lens

NPM Version repo-circleci-badge: https://img.shields.io/circleci/project/github/Ailrun/typed-f/master.svg?logo=circleci Known Vulnerabilities Supported TypeScript Version PRs Welcome

Watch on GitHub Star on GitHub

Lens for Typed-F

Installation

# for NPM>=5
npm install @typed-f/lens
# or
npm i @typed-f/lens
# for NPM<5
npm install --save @typed-f/lens
# or
npm i -S @typed-f/lens

Usage Example

Suppose that you have complex object, and want to update part of it, immutably. For example, you want to update oldObject.user.books[0].price to 22 in following code, without mutable modification of the object.

const oldObject = {
  info: 4,
  user: {
    id: 4,
    books: [
      {
        id: 23,
        title: 'First Book',
        publisher: {
          id: 123,
          name: 'Some Pub',
        },
        price: 20,
      },
      {
        id: 43,
        title: 'Other Book',
        publisher: {
          id: 154,
          name: 'Pub Beer',
        },
        price: 32,
      },
    ],
  },
};

You would do something like this.

const newObject = {
  ...oldObject,
  user: {
    ...oldObject.user,
    books: [
      {
        ...oldObject.user.books[0],
        price: 22,
      },
      oldObject.user.books[1],
    ],
  },
};

What really important is just price: 22 part, but you need many boilerplates to do that. With Lens, you can achieve this with following code.

const objectLens = new LensGenerator<typeof oldObject>().fromKeys();
const newObject = objectLens
  .focusTo('user')
  .focusTo('books')
  .focusTo(0)
  .focusTo('price')
  .set()(oldObject)(22);

You can write even nicer (well, actually it's matter of taste :) ) syntax with ES6 Proxy (Be careful about browser compatibility! You may consider using this polyfill.)

const objectLens = new LensGenerator<typeof oldObject>().byProxy();
const newObject = objectLens
  .user
  .books[0]
  .price
  .set()(oldObject)(22);

I added some linefeeds to be visually pleasing. However, of course, you can write those accesses in a line.

const objectLens = new LensGenerator<typeof oldObject>().byProxy();
const newObject = objectLens.user.books[0].price.set()(oldObject)(22);

APIs

This package includes following classes

Lens and LensS (specially Lens) just include some boring APIs, and really useful utilities come from LensGenerator.

Methods of Lens

Constructor of Lens

constructor(get: Fun<[S], A>, set: Fun<[S], Fun<[B], T>>)

Making a lens with getter function and setter function. Those functions will be invoked by lens.get() and lens.set().
Type parameter A is type for the part of S you want to focus in, and S is type for whole state. B is type for modified value for position of A, and T is type for result whole state of modification.

get

get(this: Lens<A, S, B, T>): Fun<[S], A>

Returns getter that this lens has. Getter will take initial state (S) and return a value focused in (A).

set

set(this: Lens<A, S, B, T>): Fun<[S], Fun<[B], T>>

Returns setter that this lens has. Setter will take initial state (S) and new value (B), and return a new state (T).

map

map(this: Lens<A, S, B, T>): Fun<[S], Fun<[Fun<[A], B>], T>>

Returns a mapper (function that gets a value and uses that value to generate new value) for this lens.

Methods of LensS

This class inherits Lens, so it has all Lens APIs. More specifically, LensS<A, S> extends Lens<A, S, A, S>.

Constructor of LensS

constructor(get: Fun<[S], A>, set: Fun<[S], Fun<[A], S>>)

Same with Lens constructor except that this one has fewer type parameters.

makeInner

makeInner<K extends keyof A>(this: LensS<A, S>, key: K): LensS<A[K], A>

Returns new Lens that treat A as a whole state and A[K] as a focused target. For example, when you have some object like

interface Manager {
  name: string;
}
interface Library {
  manager: Manager;
}
interface Obj {
  library: Library;
}
const obj: Obj = { library: { manager: { name: 'whoever' } } };

and you have a lens libraryFromObjLens: LensS<Library, Obj>, calling libraryFromObjLens.makeInner('manager') will give you managerFromLibraryLens: LensS<Manager, Library>, i.e., a lens to get manager from library and set manager in library. For instance,

// Getting result will be `{ manager: { name: 'whoever' } }`, i.e., `Library` object.
libraryFromObjLens.get()(obj);
// Setting result will be `{ library: { manager: { name: 'oh-my' } } }`, i.e., `Obj` object.
libraryFromObjLens.set()(obj)({ manager: { name: 'oh-my' } });

// Getting result will be `{ name: 'whoever' }`, i.e., `Manager` object.
managerFromObjLens.get()(obj.library);
// Setting result will be `{ manager: { name: 'pardon?' } }`, i.e., `Library` object.
managerFromObjLens.set()(obj.library)({ name: 'pardon?' });

// Following get will gives a type error.
managerFromObjLens.get()(obj);
// Following set will gives a type error.
managerFromObjLens.set()(obj)({ name: 'pardon?' });

If you want to make LensS<Manager, Obj>, i.e., a lens to get library.author from obj, and to modify library.author in obj, see focusTo.

focusTo

focusTo<K extends keyof A>(this: LensS<A, S>, key: K): LensS<A[K], S>

Returns new Lens that goes deeper to A[K]. For example, when you have some object like

interface Manager {
  name: string;
}
interface Library {
  manager: Manager;
}
interface Obj {
  library: Library;
}
declare const obj: Obj;

and you have a lens libraryFromObjLens: LensS<Library, Obj>, calling libraryFromObjLens.focusTo('manager') will give you managerFromObjLens: LensS<Manager, Obj>, i.e., a lens to get manager from obj and set manager in obj. To make a lens for focusing in Manager from Library, see makeInner.

Methods of LensGenerator

In following type signatures, S comes from LensGenerator class, i.e., LensGenerator<S> is this. However, I will not write this: LensGenerator<S> in type signatures, since following methods do not use this.

Constructor of LensGenerator

constructor()

Constructor for LensGenerator is only for type parameter. See this issue for discussion about this.

fromKey

fromKey<K extends keyof S>(key: K): LensS<S[K], S>

Construct a LensS to access state[key] and to set the value of state[key] in state: S.

fromKeys

fromKeys(...keys: []): LensS<S, S>
fromKeys<K0 extends keyof S>(...keys: [K0]): LensS<S[K0], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0]>(...keys: [K0, K1]): LensS<S[K0][K1], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0], K2 extends keyof S[K0][K1]>(...keys: [K0, K1, K2]): LensS<S[K0][K1][K2], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0], K2 extends keyof S[K0][K1], K3 extends keyof S[K0][K1][K2]>(...keys: [K0, K1, K2, K3]): LensS<S[K0][K1][K2][K3], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0], K2 extends keyof S[K0][K1], K3 extends keyof S[K0][K1][K2], K4 extends keyof S[K0][K1][K2][K3]>(...keys: [K0, K1, K2, K3, K4]): LensS<S[K0][K1][K2][K3][K4], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0], K2 extends keyof S[K0][K1], K3 extends keyof S[K0][K1][K2], K4 extends keyof S[K0][K1][K2][K3], K5 extends keyof S[K0][K1][K2][K3][K4]>(...keys: [K0, K1, K2, K3, K4, K5]): LensS<S[K0][K1][K2][K3][K4][K5], S>
fromKeys<K0 extends keyof S, K1 extends keyof S[K0], K2 extends keyof S[K0][K1], K3 extends keyof S[K0][K1][K2], K4 extends keyof S[K0][K1][K2][K3], K5 extends keyof S[K0][K1][K2][K3][K4], K6 extends keyof S[K0][K1][K2][K3][K4][K5]>(...keys: [K0, K1, K2, K3, K4, K5, K6]): LensS<S[K0][K1][K2][K3][K4][K5][K6], S>
fromKeys<P>(...keys: any[]): LensS<P, S>

Construct a LensS to access state[keys[0]][keys[1]]... and set the value of it in state: S.

byProxy

byProxy(): LensSProxy<S, S>

Warning: this API uses ES6 Proxy. Be careful about browser compatibility! This polyfill also does not work for this since this API uses dynamic properties.

Returns a Proxy object that allow you to make lens for any depth of properties. For example, when you have obj: Obj (Obj type from the example of makeInner), you can use

const objProxy = new LensGenerator<Obj>().byProxy();
const nameProxy = objProxy
  .library // this can be used as `LensS<Library, Obj>`
  .manager // this can be used as `LensS<Manager, Obj>`
  .name; // this can be used as `LensS<string, Obj>`
// Setting will returns `{ library: { manager: { name: '123' } } }`, i.e., `Obj` object.
nameProxy.set()(obj)('123');