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

dyna-switch

v1.1.2

Published

The dyna-switch

Downloads

121

Readme

dynaSwitch

dynaSwitch combines the benefits of JavaScript's switch statement and allows inline value returns.

How to use JavaScript's switch statement for inline value

Suppose we have the following themes:

interface ITheme {
  color: string;
  backgroundColor: string;
}

const lightTheme: ITheme = {color: 'black', backgroundColor: 'white'};
const darkTheme: ITheme = {color: 'white', backgroundColor: 'black'};
const redTheme: ITheme = {color: 'red', backgroundColor: 'white'};

We can write the following code to obtain the appropriate theme based on a string value:

const themeName: string = getUIThemeName();

const theme: ITheme = (() => {
  switch (themeName) {      // The value that is going to be tested
    case 'light':           // The cases
      return lightTheme;
    case 'dark':
      return darkTheme;
    case 'red':
      return redTheme;
    default:
      return lightTheme;    // Default value
  }
})();

Introducing dynaSwitch

With dynaSwitch, we can achieve the same result in a more concise manner:

const themeName: string = getUIThemeName();

const result = dynaSwitch<ITheme>(
  themeName,                // The value that is going to be tested    
  lightTheme,               // Default value
  {                         // Cases (as object)
    light: lightTheme,
    dark: darkTheme,
    red: () => redTheme,    // The value would be returned by a function also
  },
);

Benefits

  • Organized like JavaScript's switch statement
  • Less code, more readable
  • Prevents accidental fall-through cases
  • Always returns a value (the second argument serves as the default value)
  • Provides type safety in TypeScript, ensuring the expected value is returned
  • The cases dictionary argument can be reused and can handle more complex objects.

Using dynaSwitch with functions

In this example, we utilize functions instead of values in the dynaSwitch cases. This allows us to have variables with the same names inside the functions, something not possible with the traditional switch statement unless closures are used. This feature is particularly useful in Redux reducers, where the cases often require the use of the same variable names.

const themeName: string = getUIThemeName();

const result = dynaSwitch<ITheme>(
  themeName,                // The value that is going to be tested    
  lightTheme,               // Default value
  {                         // Dictionary with the cases
    light: () => {
      const isUserAdmin: boolean = getUserAdmin();
      const theme = { ...lightTheme };
      theme.profile.color = 'red';
      return theme;
    },
    dark: () => {
      const isUserAdmin: boolean = getUserAdmin();
      const theme = { ...darkTheme };
      theme.profile.color = 'maroon';
      return theme;
    },
    red: () => {
      const isUserAdmin: boolean = getUserAdmin();
      const theme = { ...redTheme };
      theme.profile.color = 'pink';
      return theme;
    },
  },
);

Introducing dynaSwitchEnum

With dynaSwitchEnum, you can easily achieve super type-safe values for each option of an Enum, thanks to TypeScript's internal Record feature. This means that if the Enum is modified in the future, you will receive TypeScript errors during compilation for any missing or modified Enum options.

enum ETheme {
  DARK = "DARK",
  LIGHT = "LIGHT",
  REDISH = "REDISH",
}

interface ITheme {
  color: string;
  backgroundColor: string;
}

const themeSetups: Record<ETheme, ITheme> = {
  [ETheme.LIGHT]: {
    color: 'black', backgroundColor: 'white',
  },
  [ETheme.DARK]: {
    color: 'white', backgroundColor: 'black',
  },
  [ETheme.REDISH]: {
    color: 'red', backgroundColor: 'white',
  },
};

dynaSwitchEnum<ETheme, ITheme>(ETheme.LIGHT, themeSetups).color; // returns "black"

dynaSwitchEnum<ETheme, ITheme>("something", themeSetups).color; // not compilable, due to TS!

Alternatively, you can define the dictionary directly. This is especially helpful when you want to convert an enum to a React component prop.

dynaSwitchEnum<ETheme, string>(
  ETheme.REDISH,
  {
    [ETheme.LIGHT]: 'Light',
    [ETheme.DARK]: 'Darky',
    [ETheme.REDISH]: 'Redish',
  },
); // This returns "Redish"!

Benefits

  • Provides super type safety for both the Enum and the returned value
  • Always returns a value

Introducing dynaSwitchIf

dynaSwitchIf is similar to dynaSwitch, but instead of using a dictionary, it employs an array of "if" statements. The first valid "if" statement is executed. This approach makes it easier to assign values compared to using keys in a dictionary.

This dynaSwitch implementation works like an "if-else" statement.

Example:

const themeName = 'dark';

const theme = dynaSwitchIf<ITheme>(
  themeName,                                // The value that is going to be tested
  lightTheme,                               // Default value
  [
    {if: 'light', then: lightTheme},
    {if: 'dark', then: () => darkTheme},    // The `then` would be a function
    {if: 'red', then: redTheme},
  ],
);

expect(theme.color).toBe('white');

API

TypeScript signatures of the methods:

dynaSwitch

export interface IDynaSwitchCasesDic<TResult = any> {
  [enumCase: string]: TResult | (() => TResult);
}

export const dynaSwitch = <TResult = any, TTestValue = string | number>(
  testValue: TTestValue,
  defaultValue: TResult | (() => TResult),
  cases: IDynaSwitchCasesDic<TResult>,
) => TResult;

dynaSwitchEnum

export const dynaSwitchEnum = <TEnum extends string | number | symbol, TResult>(
  testValue: TEnum,
  cases: Record<TEnum, TResult>,
) => TResult;

dynaSwitchIf

export type TDynamicValue<T = any> = T | (() => T);

export const dynaSwitchIf = <TResult = any, TTestValue = any>(
  testValue: TTestValue,
  defaultValue: TDynamicValue<TResult>,
  cases: { if: TDynamicValue<TTestValue>; then: TDynamicValue<TResult> }[],
) => TResult;