Last active
December 2, 2022 22:34
-
-
Save kennethkeim/3f22e509e897963c8a325ef083c0eb20 to your computer and use it in GitHub Desktop.
Credits to Michael Lowenstein
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const defaultTo = (a: any, b: any): any => | |
a == null || Object.is(a, NaN) ? b : a; | |
export const remove = (data: any[], loopFunc: any): any[] => { | |
return data.filter(() => { | |
return !loopFunc.apply(this); | |
}); | |
}; | |
export const omitThis = (key: string, { [key]: _, ...obj }) => obj; | |
export const round = (val: number, precision: number): number => { | |
const decimalFactor = Math.pow(10, precision); | |
return Math.round(val * decimalFactor) / decimalFactor; | |
}; | |
export const slice = (inputs: any[], from: number, to?: number): any[] => { | |
return to ? inputs.slice(from, to) : inputs.slice(from); | |
}; | |
export const isEqual = (base: any, match: any): boolean => { | |
const baseType = typeof base; | |
const matchType = typeof match; | |
if (baseType != matchType) { | |
return false; | |
} | |
if (baseType == "string" || baseType == "number" || baseType == "boolean") { | |
return base === match ? true : false; | |
} | |
return Object.entries(base).toString() === Object.entries(match).toString(); | |
}; | |
export const clone = (input: any): any => { | |
if (Array.isArray(input)) { | |
const output: any[] = []; | |
input.forEach((ip) => { | |
output.push(clone(ip)); | |
}); | |
return output; | |
} else { | |
return { ...input }; | |
} | |
}; | |
export const cloneDeep = (inputs: any): any => { | |
if (Array.isArray(inputs)) { | |
const output: any[] = []; | |
inputs.forEach((ip) => { | |
output.push(cloneDeep(ip)); | |
}); | |
return output; | |
} else { | |
return JSON.parse(JSON.stringify(inputs)); | |
} | |
}; | |
export const union = (...data: any[]): any => { | |
return data.reduce((first, next) => Array.from([...first, ...next])); | |
}; | |
export const unionBy = (iteratee: any, ...inputs: any[]) => { | |
let united: any[] = []; | |
for (const ip of inputs) { | |
const mapped = ip.map(iteratee); | |
const unionMapped = united.map(iteratee); | |
const uniques = mapped.filter((i: any) => !unionMapped.includes(i)); | |
united = [...united, ...uniques]; | |
} | |
return united; | |
}; | |
export const unionWith = (comparator: any, ...inputs: any[]) => { | |
let united: any[] = []; | |
for (const ip of inputs) { | |
const uniques = ip.filter( | |
(i: any) => !united.find((u) => comparator(i, u)), | |
); | |
united = [...united, ...uniques]; | |
} | |
return united; | |
}; | |
export const integrate = (oldData: any[], newData: any[]) => { | |
if (Array.isArray(oldData)) { | |
return oldData.concat(newData); | |
} | |
return newData; | |
}; | |
/* eslint-disable prefer-const */ | |
/** General Utility Functions: */ | |
export const groupBy = function (array: any[], key: string): any[] { | |
return array.reduce(function (obj, x) { | |
(obj[x[key]] = obj[x[key]] || []).push(x); | |
return obj; | |
}, {}); | |
}; | |
export const unique = function (array: any[]): any[] { | |
let vals = ""; | |
let keys: string[]; | |
let newarray: any[]; | |
let unique: any; | |
unique = {}; | |
newarray = []; | |
array.forEach((item) => { | |
vals = ""; | |
keys = item ? Object.keys(item) : []; | |
keys.forEach((key) => { | |
vals += item[key] + " "; | |
}); | |
if (!unique[vals]) { | |
newarray.push(item); | |
} | |
unique[vals] = item; | |
}); | |
return newarray; | |
}; | |
export const uniqBy = (data: any[], predicate: any): any => { | |
const cb = | |
typeof predicate === "function" | |
? predicate | |
: (o: { [x: string]: any }) => o[predicate]; | |
return [ | |
...data | |
.reduce((map, item) => { | |
const key = item === null || item === undefined ? item : cb(item); | |
map.has(key) || map.set(key, item); | |
return map; | |
}, new Map()) | |
.values(), | |
]; | |
}; | |
export const getSorted = function (prop: string) { | |
return function (a: any, b: any) { | |
if (a[prop] > b[prop]) { | |
return 1; | |
} | |
if (a[prop] < b[prop]) { | |
return -1; | |
} | |
return 0; | |
}; | |
}; | |
/** Creates a random 4-char chunk which will be | |
* concatenated with other chunks to make our | |
* randomly-generated GUID for batch-posts. */ | |
export const segment = function (): string { | |
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); | |
}; | |
/** Creates a random 32-character GUID for | |
* string-identifiers values if needed. */ | |
export const generate = function (): string { | |
return ( | |
segment() + | |
segment() + | |
segment() + | |
"4" + | |
segment().substr(0, 3) + | |
segment() + | |
segment() + | |
segment() + | |
segment() | |
).toLowerCase(); | |
}; | |
export const isEmpty = (value: any): boolean => { | |
return ( | |
value == null || | |
(typeof value === "object" && Object.keys(value).length === 0) || | |
(typeof value === "string" && value.trim().length === 0) | |
); | |
}; | |
export const orderBy = ( | |
data: any[], | |
keys: string[] | number[] | string, | |
): any => { | |
const sortKeys = Array.isArray(keys) ? keys : [keys]; | |
return data.map((first: any, next: any) => { | |
return sortKeys.forEach((sortKey: any) => { | |
return first[sortKey] > next[sortKey] | |
? 1 | |
: next[sortKey] > first[sortKey] | |
? -1 | |
: 0; | |
}); | |
}); | |
}; | |
type GetIndexedField<T, K> = K extends keyof T | |
? T[K] | |
: K extends `${number}` | |
? "0" extends keyof T | |
? undefined | |
: number extends keyof T | |
? T[number] | |
: undefined | |
: undefined; | |
type FieldWithPossiblyUndefined<T, Key> = | |
| GetFieldType<Exclude<T, undefined>, Key> | |
| Extract<T, undefined>; | |
type IndexedFieldWithPossiblyUndefined<T, Key> = | |
| GetIndexedField<Exclude<T, undefined>, Key> | |
| Extract<T, undefined>; | |
export type GetFieldType<T, P> = P extends `${infer Left}.${infer Right}` | |
? Left extends keyof T | |
? FieldWithPossiblyUndefined<T[Left], Right> | |
: Left extends `${infer FieldKey}[${infer IndexKey}]` | |
? FieldKey extends keyof T | |
? FieldWithPossiblyUndefined< | |
IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey>, | |
Right | |
> | |
: undefined | |
: undefined | |
: P extends keyof T | |
? T[P] | |
: P extends `${infer FieldKey}[${infer IndexKey}]` | |
? FieldKey extends keyof T | |
? IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey> | |
: undefined | |
: undefined; | |
export const getAny = < | |
TData, | |
TPath extends string | number, | |
TDefault = GetFieldType<TData, TPath>, | |
>( | |
data: TData, | |
path: TPath, | |
defaultValue?: TDefault, | |
): GetFieldType<TData, TPath> | TDefault | any => { | |
if (typeof path === "number") { | |
return getAny(Object.values(data as any)[path], path); | |
} | |
const value = path | |
.toString() | |
.split(/[.[\]]/) | |
.filter(Boolean) | |
.reduce<GetFieldType<TData, TPath>>( | |
(value: any, key: string | number) => (value as any)?.[key], | |
data as any, | |
); | |
return value !== undefined ? value : (defaultValue as TDefault); | |
}; | |
export const omitFrom = (input: any, keys: string[]): any => { | |
const output = { ...input }; | |
const inputKeys = Object.keys(output); | |
inputKeys.forEach((inputKey: string) => { | |
if (keys.includes(inputKey) && output[inputKey]) { | |
delete output[inputKey]; | |
} else { | |
const innerKeys = Object.keys(output[inputKey]); | |
innerKeys.forEach((innerKey: string) => { | |
if (keys.includes(innerKey)) { | |
delete output[inputKey][innerKey]; | |
} | |
}); | |
} | |
}); | |
return output; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment