An open API service indexing awesome lists of open source software.

https://github.com/aneldev/dyna-switch

Inline switch that returns value. Write complex switch in clean way.
https://github.com/aneldev/dyna-switch

Last synced: 9 months ago
JSON representation

Inline switch that returns value. Write complex switch in clean way.

Awesome Lists containing this project

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:

```typescript
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:

```typescript
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:

```typescript
const themeName: string = getUIThemeName();

const result = dynaSwitch(
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.

```typescript
const themeName: string = getUIThemeName();

const result = dynaSwitch(
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.

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

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

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

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

dynaSwitchEnum("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.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:

```typescript
const themeName = 'dark';

const theme = dynaSwitchIf(
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

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

export const dynaSwitch = (
testValue: TTestValue,
defaultValue: TResult | (() => TResult),
cases: IDynaSwitchCasesDic,
) => TResult;
```

## dynaSwitchEnum

```typescript
export const dynaSwitchEnum = (
testValue: TEnum,
cases: Record,
) => TResult;
```

## dynaSwitchIf

```typescript
export type TDynamicValue = T | (() => T);

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