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 🙏

© 2025 – Pkg Stats / Ryan Hefner

map-fn

v0.3.2

Published

A set of utility functions to map one type of values to another one with ease

Readme

map-fn

Build Coverage Status

A set of utility functions to map one type of values to another one with ease.

Installation

pnpm add map-fn -P

Build

pnpm build

Develop

pnpm dev

Test

pnpm lint
pnpm test
pnpm test:coverage

Basic usage

import { createMapFn } from 'map-fn';

type A = 'foo' | 'bar' | 'baz';
type B = 'FOO' | 'BAR' | 'BAZ';

const mapAB = createMapFn<A, B>({
  foo: 'FOO',
  bar: 'BAR'
});

console.log(mapAB('foo')); // 'FOO'
console.log(mapAB('bar')); // 'BAR'

If no corresponding value is provided then MappingError will be thrown:

console.log(mapAB('baz')); // MappingError: Unable to map "baz", default value is not provided

You can provide alternative error message:

const mapAB = createMapFn<A, B>({
  foo: 'FOO',
  bar: 'BAR'
}, { errorMessage: (input: A): string => `No value found for "${input}"` });

console.log(mapAB('baz')); // MappingError: No value found for "baz" 

or

const mapAB = createMapFn<A, B>({
  foo: 'FOO',
  bar: 'BAR'
});

console.log(mapAB('baz', { errorMessage: (input: A): string => `No value found for "${input}"` })); // Mapping error: No value found for "baz"

There are few options available to avoid MappingError in such cases:

  1. Provide default value in createMapFn:

    const mapAB = createMapFn<A, B>({
      foo: 'FOO',
      bar: 'BAR'
    }, { defaultValue: 'BAZ' });
       
    console.log(mapAB('baz')); // 'BAZ'
  2. Provide default value calling mapping function:

    const mapAB = createMapFn<A, B>({
      foo: 'FOO',
      bar: 'BAR'
    });
       
    console.log(mapAB('baz', { defaultValue: 'BAZ' })); // 'BAZ'
  3. Use customTransformer option for custom value transformation in createMapFn:

    const mapAB = createMapFn<A, B>(
      { foo: 'FOO' },
      {
        customTransformer: (value: A) => B {
          return value === 'bar' ? 'BAZ' : 'BAR';
        }
      }
    );
       
    console.log(mapAB('bar')); // 'BAZ'
    console.log(mapAB('baz')); // 'BAR'
  4. Provide customTransformer option calling mapping function:

    const mapAB = createMapFn<A, B>({ foo: 'FOO' });
    const customTransformer = (value: A) => B {
      return value === 'bar' ? 'BAZ' : 'BAR';
    };
       
    console.log(mapAB('bar', { customTransformer })); // 'BAZ'
    console.log(mapAB('baz', { customTransformer })); // 'BAR'
  5. Use createMapFnUndefined instead. Please note that output type will be B | undefined (not B):

    const mapAB = createMapFnUndefined<A, B>({
      foo: 'FOO',
      bar: 'BAR'
    });
       
    console.log(mapAB('baz')); // undefined

Please note that defaultValue can also be a function similar to customTransformer except it can't return undefined. You can combine both customTransformer and defaultValue, the former takes precedence.

Reverse mapping

Sometimes you may want to make backward transformations without need to declare reversed map. createReverseMap and createReverseMapUndefined functions are created for this purpose. The only restriction here is that type of original map values must extend number or string.

const mapBA = createReverseMap<A, B>({
  foo: 'FOO',
  bar: 'BAR'
});

console.log(mapBA('FOO')); // 'foo'
console.log(mapBA('BAR')); // 'bar'

The same options as for basic mapping function creators are available for reverse function creators, the difference is input/output generic types are swapped.

Mapping with argument

For advanced cases one may consider using createArgumentMapFn or createArgumentMapFnUndefined mapping function creators. They provide additional input argument in mapping configuration:

import { createArgumentMapFn } from '../lib';

abstract class Person {
  id: number;

  constructor(id: number) {
    this.id = id;
  }
  
  ...
}

class Musician implements Person { ... }

class Poet implements Person { ...}

type PersonType = 'musician' | 'poet';

const mapPerson = createArgumentMapFn<PersonType, Person, number>({
  musician: (id) => new Musician(id),
  poet: (id) => new Poet(id)
});

const musician = mapPerson('musician', 1);
console.log(musician instanceof Musician); // true
console.log(musician instanceof Poet); // false

const poet = mapPerson('poet', 2);
console.log(poet instanceof Musician); // false
console.log(poet instanceof Poet); // true

Strict

Mapping functions described above don't guarantee that all input values have matched output ones (that's why defaultValue and customTransformer exist). If you want to control exhaustive matches between input and output values in TypeScript then strict functions come to the party:

const mapAB = createMapFnStrict<A, B>({
  foo: 'FOO',
  bar: 'BAR',
  baz: 'BAZ'
});

The following will trigger type checking error because mapping object is incomplete:

const mapAB = createMapFnStrict<A, B>({
  foo: 'FOO',
  bar: 'BAR'
}); // baz property is missing

This is the full list of strict functions:

  • createMapFnStrict;
  • createMapFnStrictUndefined;
  • createReverseMapFnStrict;
  • createReverseMapFnStrictUndefined;
  • createArgumentMapFnStrict;
  • createArgumentMapFnStrictUndefined.

License

MIT