toggle-corp/fujs

View on GitHub
src/object.ts

Summary

Maintainability
A
30 mins
Test Coverage
A
95%
import { isNotDefined } from './core';
import { isList, isObject } from './type';

/**
 * Pick only certain keys from an object
 * @param obj
 * @param keys
 */
export const pick = <T extends object>(obj: T, keys: (keyof T)[]) => keys.reduce(
    (acc, key) => ({ ...acc, [key]: obj[key] }),
    {},
);

/**
 * Remove a certain key from an object
 * @param obj
 * @param key
 */
export function removeKey<T extends object>(obj: T, key: keyof T) {
    if (isNotDefined(obj) || !(key in obj)) {
        return obj;
    }

    const newObj = { ...obj };
    // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
    delete newObj[key];
    return newObj;
}

/**
 * Get key of the first element in an object
 * @param obj
 * @param value
 */
export function getFirstKeyByValue<T extends object>(obj: T, value: unknown): string | undefined {
    return Object.keys(obj).find((key) => obj[key as keyof T] === value);
}

/**
 * Identify if object has no data
 * @param obj
 * @param invalids list of values that aren't considered as data
 */
export function doesObjectHaveNoData(obj: unknown, invalids: unknown[] = []): boolean {
    // NOTE: null and NaN are truthy values here
    if (obj === undefined) {
        return true;
    }

    if (isList(obj)) {
        if (obj.length <= 0) {
            return true;
        }
        return obj.every((e) => doesObjectHaveNoData(e, invalids));
    }

    if (isObject(obj)) {
        if (Object.keys(obj).length <= 0) {
            return true;
        }
        return Object.keys(obj).every(
            (key) => doesObjectHaveNoData(obj[key as keyof object], invalids),
        );
    }

    return invalids.includes(obj);
}