# Top 10 Utilities You May Need for Your TypeScript Projects

<img alt="Image for post" class="t u v fx aj" src="https://miro.medium.com/max/8000/0*pfz8bTnT2lScISkd" width="4000" height="3000" srcSet="https://miro.medium.com/max/552/0*pfz8bTnT2lScISkd 276w, https://miro.medium.com/max/1104/0*pfz8bTnT2lScISkd 552w, https://miro.medium.com/max/1280/0*pfz8bTnT2lScISkd 640w, https://miro.medium.com/max/1456/0*pfz8bTnT2lScISkd 728w, https://miro.medium.com/max/1632/0*pfz8bTnT2lScISkd 816w, https://miro.medium.com/max/1808/0*pfz8bTnT2lScISkd 904w, https://miro.medium.com/max/1984/0*pfz8bTnT2lScISkd 992w, https://miro.medium.com/max/2160/0*pfz8bTnT2lScISkd 1080w, https://miro.medium.com/max/2700/0*pfz8bTnT2lScISkd 1350w, https://miro.medium.com/max/3240/0*pfz8bTnT2lScISkd 1620w, https://miro.medium.com/max/3780/0*pfz8bTnT2lScISkd 1890w, https://miro.medium.com/max/4320/0*pfz8bTnT2lScISkd 2160w, https://miro.medium.com/max/4800/0*pfz8bTnT2lScISkd 2400w" sizes="100vw"/>

Photo by [Jeff Sheldon](https://unsplash.com/@ugmonk?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

JS|TS By Example

# Top 10 Utilities you may need for your TypeScript Projects

You work on multiple projects. Most of the time you repeat your self while writing common util functions. Here are some of the most useful utilities that you can use for your TypeScript or JavaScript

**1\. compact:** Compact is normally used to remove the **falsy** value from _an Array._ There are multiple variations of it.

**Simple Variant:** filter out **falsy** values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`).


```
// How to use it
compact([0, 1, false, 2, "", 3, "a", Number("e") * 23, NaN, "s", 34]); _// [ 1, 2, 3, 'a', 's', 34 ]_
```


**Functional and Advanced Variation:** You can also take a function as a parameter to define the behavior of the filter.


```
// Code:
type Predicate<T> = (val: T) => boolean;

const compact = <T = any>(fn: Predicate<T>, arr: T[] = []) => arr.filter(fn);
const removeFalsy = curry(compact, 2)(Boolean);
const removeNull = curry(compact, 2)((v: any) => v !== null);

// How to use it
removeFalsy([0, false, "", 3, "a", Number("e") * 23, NaN, null])
// [ 3, 'a']

removeNull([0, false, "", 3, "a", Number("e") * 23, NaN, null]);
// [ 0, false, '', 3, 'a', NaN, NaN, 's' ]
```


_If you noticed, I am using function curry to make compact more functional, and reusable. We will learn curry later in this tutorial._

**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/compact](https://decipher.dev/30-seconds-of-typescript/docs/compact)

**2\. contains** The other useful function, I used in most of the projects. After ES 2015, JavaScript does have includes. However, most of the time you end-up error like _toLowerCase_ _of undefined is not function_. You have to handle boundary cases.


```
// Code:
const contains = (s1: string, s2: string = "") =>
s1.toLowerCase().indexOf(s2.toLowerCase()) !== -1

// How to use it
contains("Text1", "Ext"); _// true_ contains("Text1", "et"); _// false_
```


Above util is _case insensitive_ in nature. You can update according to your need.

To learn more: [https://decipher.dev/30-seconds-of-typescript/docs/contains](https://decipher.dev/30-seconds-of-typescript/docs/contains)

**3\. curry:** If you love **functional programming**. You can’t skip the curry method in your toolbox. curry is one of the most basic needs of functional programming. However, Defining curry function is TypeScript could be a challenge. Bellow example I defined based on my knowledge. You can find a better variant of it online.

**Concept of curry:** [https://en.wikipedia.org/wiki/Currying](https://en.wikipedia.org/wiki/Currying)


```
// Code:
const curry = (fn: Function, arity = fn.length, ...args: any[]): any => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);

// How to use it 

const removeFalsy = curry(compact, 2)(Boolean);
const removeNull = curry(compact, 2)((v: any) => v !== null);
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/curry](https://decipher.dev/30-seconds-of-typescript/docs/curry)

![Image for post](https://miro.medium.com/max/60/0*GMNCSt3yujo9odXq?q=20)

<img alt="Image for post" class="t u v fx aj" src="https://miro.medium.com/max/9182/0*GMNCSt3yujo9odXq" width="4591" height="3061" srcSet="https://miro.medium.com/max/552/0*GMNCSt3yujo9odXq 276w, https://miro.medium.com/max/1104/0*GMNCSt3yujo9odXq 552w, https://miro.medium.com/max/1280/0*GMNCSt3yujo9odXq 640w, https://miro.medium.com/max/1400/0*GMNCSt3yujo9odXq 700w" sizes="700px"/>

Photo by [Alexander Schimmeck](https://unsplash.com/@alschim?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

**4\. delay:** delay is very useful in testing some asynchronous methods. This helps to put some virtual delay to mimic the network call or any async side-effect.

**Simple Variant:**


```
// Code
const delay = (fn: Function, wait: number, ...args: any[]) =>   setTimeout(fn, wait, ...args);

// How to use it
 delay(
  function (text) {
    console.log(text);
  },
  1000,
  "later"
); 
_// Logs 'later' after one second._
```


**Promise Variant:** If you needed you can create a Promise variant of it. Just wrap delay in promise.


```
// Code
const delayedPromise = (wait: number = 300, ...args: any[]) => 
new Promise((resolve) => {
  delay(resolve, wait, ...args);
});
// How to use it 
(async function () {
  await delayedPromise();
  console.log("Print after delay");
})(); 
// Print after delay
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/delay](https://decipher.dev/30-seconds-of-typescript/docs/delay)

**5\. unique:** This is used to get the unique values in a given array. This could also have multiple variants. The simplest one uses Set to push values and collect unique value.


```
// Code
const unique = (arr: any[]) => [...new Set(arr)];

// How to use it 
unique([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5]
```


You can also pass a function to define the uniqueness of the value.


```
// Code
const uniqueBy = (fn: Predicate, arr: any[]) =>
  arr.reduce((acc, v) => {
    if (!acc.some((x: any) => fn(v, x))) acc.push(v);
    return acc;
  }, []);

// How to use it 
uniqueBy(
(a: any, b: any) => a.id == b.id,
  [
    { id: 0, value: "a" },
    { id: 1, value: "b" },
    { id: 2, value: "c" },
    { id: 1, value: "d" },
    { id: 0, value: "e" },
  ],
); 
// [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ]
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/unique](https://decipher.dev/30-seconds-of-typescript/docs/unique)

**6\. sum:** Sum is one of the simplest but useful method you may want in your util library. You can use [_Array.reduce_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) to sum the value.


```
// Code
const sum = (...arr: number[]) => [...arr].reduce((acc, val) => acc + val, 0);

// How to use it
sum(1, 2, 3, 4); // 10
sum(...[1, 2, 3, 4]); // 10
```


You can also pass a function as a parameter to extract the value to sum.


```
// Code
const sumBy = <T = any>(arr: T[], fn: string | ((a: T) => number)) => {
  return arr
    .map(typeof fn === "function" ? fn : (val: any) => val[fn])
    .reduce((acc, val) => acc + val, 0);
};

// How to use it
sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], (o) => o.n); // 20
sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], "n"); // 20
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/sum](https://decipher.dev/30-seconds-of-typescript/docs/sum)

![Image for post](https://miro.medium.com/max/60/0*l-h2O-VlrhFPTPd7?q=20)

<img alt="Image for post" class="t u v fx aj" src="https://miro.medium.com/max/9216/0*l-h2O-VlrhFPTPd7" width="4608" height="2592" srcSet="https://miro.medium.com/max/552/0*l-h2O-VlrhFPTPd7 276w, https://miro.medium.com/max/1104/0*l-h2O-VlrhFPTPd7 552w, https://miro.medium.com/max/1280/0*l-h2O-VlrhFPTPd7 640w, https://miro.medium.com/max/1400/0*l-h2O-VlrhFPTPd7 700w" sizes="700px"/>

Photo by [Edu Grande](https://unsplash.com/@edgr?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

**7\. sortBy:** Sorting an array can be easily done using [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort). But saying so, There are still many edge cases you may want to handle in your util library. Here is some variation of my sortBy method.

**Code:**


```
type SortByFunc<T> = (s1: T, s2: T) => number;
enum SortByOrder {
  ASC = 1,
  DESC = -1,
}
const sortBy = <T = any>(
  arr: T[],
  $fn: SortByFunc<T> = (s1: any, s2: any) =>
    order * String(s1).localeCompare(String(s2)),
  order: SortByOrder = SortByOrder.ASC
) => {
  let fn = $fn;
  return [...arr].sort(fn);
};
```


**How to use it:**


```
sortBy([1, 2, 4, 3, 4, -1]); // [-1, 1, 2, 3, 4, 4]
sortBy(["Test", "test"]); // ["Test", "test"]
// Descending
sortBy([1, 2, 4, 3, 4, -1], undefined, -1); 
// [4, 4, 3, 2, 1, -1]

sortBy([{ name: "02" }, { name: "01" }], (s1: any, s2: any) =>
  s1.name.localeCompare(s2.name)
); //[{ name: "01" }, { name: "02" }]

// Descending
sortBy(
  [{ name: "02" }, { name: "01" }],
  (s1: any, s2: any) => -1 * s1.name.localeCompare(s2.name)
); 
//[{ name: "02" }, { name: "01" }]
```


You also may want to sortBy key(passing the key name of the object to sort).


```
// sortByKey
enum SortByOrder {
  ASC = 1,
  DESC = -1,
}
const sortByKey = <T = any>(
  arr: T[],
  key: string,
  order: SortByOrder = SortByOrder.ASC
) => {
  return [...arr].sort(
    (s1: any, s2: any) => order * String(s1[key]).localeCompare(String(s2[key]))
  );
};
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/sortBy](https://decipher.dev/30-seconds-of-typescript/docs/sortBy)

**8\. randomInt:** JavaScript is awesome and the same time is has a weird side of it. Generating a _random integer_ in a given _range_ could be one of the use cases for you.


```
// Code
const randomInt = (min = 0, max = 100) =>
  Math.floor(Math.random() * (max - min + 1)) + min;
// How to use it
console.log(randomInt(0, 5)); // 2
console.log(randomInt()); // 2
```


By default, It will generate _Int_ between 0–100.

**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/randomInt](https://decipher.dev/30-seconds-of-typescript/docs/randomInt)

**9\. isEmpty:** JavaScript has so many types of Null/Falsy values. finding a nullify value could be one of the frustrating things in JavaScript. So having a method like isEmpty will make your util more useful.


```
// Code
const isEmpty = (val: any) => val == null || !(Object.keys(val) || val).length;

// How to use it
isEmpty([]); // true
isEmpty({}); // true
isEmpty(""); // true
isEmpty([1, 2]); // false
isEmpty({ a: 1, b: 2 }); // false
isEmpty("text"); // false
isEmpty(123); // true - type is not considered a collection
isEmpty(true); // true - type is not considered a collection
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/isEmpty](https://decipher.dev/30-seconds-of-typescript/docs/isEmpty)

**10\. orderBy:** Last but not least, orderBy. This is one of the most used methods in my library. Since now a day, the Browser can handle more complex computing. A lot of the logic has moved to the front-end. I use this method so often in my code.


```
// Code
const orderBy = <T = AnyObject>(
  arr: T[],
  props: (keyof T)[],
  orders?: ("asc" | "desc")[]
) =>
  [...arr].sort((a, b) =>
    props.reduce((acc, prop, i) => {
      if (acc === 0) {
        const [p1, p2] =
          orders && orders[i] === "desc"
            ? [b[prop], a[prop]]
            : [a[prop], b[prop]];
        acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
      }
      return acc;
    }, 0)
  );
  
// How to use it
const users = [
  { name: "fred", age: 48 },
  { name: "barney", age: 36 },
  { name: "fred", age: 40 },
];
orderBy(users, ["name", "age"], ["asc", "desc"]); 

// [{name: 'barney', age: 36}, {name: 'fred', age: 48}, {name: 'fred', age: 40}]
orderBy(users, ["name", "age"]); 

// [{name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}]
```


**To learn more:** [https://decipher.dev/30-seconds-of-typescript/docs/orderBy](https://decipher.dev/30-seconds-of-typescript/docs/orderBy)

## Honorable mentioned:

1. **groupBy: ** https://decipher.dev/30-seconds-of-typescript/docs/groupBy 

2. **formatDate:** https://decipher.dev/30-seconds-of-typescript/docs/formatDate
3. **arrayToCSV:** https://decipher.dev/30-seconds-of-typescript/docs/arrayToCSV 
4. **pluralize:** https://decipher.dev/30-seconds-of-typescript/docs/pluralize 




**Note:** If you like, You can download extension_ [_30-seconds-of-typescript_](https://marketplace.visualstudio.com/items?itemName=imdeepak.30-seconds-of-typescript)_. This will give you the code snippets. You can also consume as an_ **_npm module_** _and_ **_ES Import_**_._


```
// Import
const { mask } = require("@deepakvishwakarma/ts-util");

// ES Import_
import * as util from "https://cdn.jsdelivr.net/gh/deepakshrma/30-seconds-of-typescript/util.js";
```


**To learn more visit:** [https://decipher.dev/30-seconds-of-typescript/docs/](https://decipher.dev/30-seconds-of-typescript/docs/)
