Skip to content

Instantly share code, notes, and snippets.

@angrykoala
Last active January 23, 2024 23:07
Show Gist options
  • Save angrykoala/3ca0cca52455567aec6f0ab237ce57a8 to your computer and use it in GitHub Desktop.
Save angrykoala/3ca0cca52455567aec6f0ab237ce57a8 to your computer and use it in GitHub Desktop.
Random set of utilities for typescript
// utilify.ts - Random set of utilities for TypeScript
// by @angrykoala
// FUNCTIONS
/** Ensures input is an array, if not, turns it into an array (empty array if input is null or undefined) */
export function arrayfy<T>(raw: T | Array<T> | undefined | null): Array<T> {
if (Array.isArray(raw)) return raw;
if (raw === undefined || raw === null) return [];
else return [raw];
}
/** Awaitable version of setTimeout */
export function delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
/** Check if something is a number */
export function isNumber(n: unknown): n is number {
return typeof n === "number" && !Number.isNaN(n);
}
/** Moves an element in an array */
export function moveElement<T>(arr: Array<T>, from: number, to:number): void {
arr.splice(to, 0, arr.splice(from, 1)[0]);
}
/** Filter all elements in an array, only leaving truthy values */
export function filterTruthy(arr: Array<boolean | null | undefined | void>): Array<true>;
export function filterTruthy<T>(arr: Array<T | null | undefined | void>): Array<T>;
export function filterTruthy<T>(arr: Array<T | null | undefined | void>) {
return arr.filter(Boolean);
}
/** Generate an array of chunks of given size (last chunk may be smaller) */
export function chunkify<T>(arr: Array<T>, chunkSize: number): Array<Array<T>> {
const result: Array<Array<T>> = []
while (arr.length > 0) {
result.push(arr.splice(0, chunkSize))
}
return result
}
/** Checks if value is string */
export function isString(value: unknown): value is string {
return typeof value === "string" || value instanceof String;
}
/** Check if both arrays share at least one element */
export function haveSharedElement(arr1: Array<any>, arr2: Array<any>): boolean {
for (const element of arr1) {
if (arr2.includes(element)) return true;
}
return false;
}
/** Remove duplicate elements from an array (shallow) using a set **/
export function removeDuplicates<T>(arr:T[]): T[] {
return Array.from(new Set(arr))
}
/** Omits fields from record */
export function omitFields<T>(x: Record<string, T>, fields: string[]): Record<string, T> {
return Object.entries(x)
.filter((item) => !fields.includes(item[0]))
.reduce((acc: Record<string, T>, [key, value]) => {
acc[key] = value;
return acc;
}, {});
}
/** Removes all items matching the given item from array, returns a new array */
export function removeItem<T>(arr: Array<T>, item: T): Array<T> {
return arr.filter((i) => i !== item);
}
/** Join strings with separator if the strings are valid **/
export function joinIfExist(arr: Array<string | null | undefined | false>, separator = " "): string {
return arr.filter(Boolean).join(separator)
}
/** Checks if element is in array, and checks its type */
export function isInArray<T>(arr: Array<T> | ReadonlyArray<T>, element: unknown): element is T {
return arr.includes(element as any);
}
// TYPES
/** Nested Records helper type, supports any level of recursion. Ending in properties of type T */
export interface NestedRecord<T> extends Record<string | symbol | number, T | NestedRecord<T>> {} // Using interface to allow recursive types
/** Defines a type representing the value of an object **/
export type ValueOf<T> = T[keyof T];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment