object/object.ts

import { ObjectInterface } from "@daybrush/utils";
import { headArray, tailArray, reduceArrayF } from "../array/array";
import { exec } from "../utils";
import { CheckPromiseType, CheckObjectType, CheckPromiseObjectType, PromiseReturnType } from "../types";
/**
 * @namespace object
 */
/**
 * @memberof object
 * @typedef
 */
export type EachObjectCallbackType<T, U, R extends ObjectInterface<T | Promise<T>> = ObjectInterface<T>> =
   (value: T, key: string, obj: R) => U;

/**
 * @memberof object
 * @typedef
 */
export type ReduceObjectCallbackType<T, U, R extends ObjectInterface<U | Promise<U>> = ObjectInterface<U>> =
(previousValue: T, currentValue: U, currentIndex: string, obj: R) => T;

/**
 * @memberof object
 */
export function reduceObjectF<T, U = T>(
  callbackFn: ReduceObjectCallbackType<T, U>,
  initial: T,
  obj: ObjectInterface<U>): T {
  let cur = initial;

  for (const key in obj) {
    cur = callbackFn(cur, obj[key], key, obj);
  }
  return cur;
}

/**
 * @memberof object
 */
export function eachObjectF<T = any>(f: EachObjectCallbackType<T, void>, obj: ObjectInterface<T>):
  ObjectInterface<T> {
  for (const key in obj) {
    f(obj[key], key, obj);
  }
  return obj;
}
/**
 * @memberof object
 */
export function mapObjectF<T = any, U = any>(f: EachObjectCallbackType<T, U>, obj: ObjectInterface<T>):
  ObjectInterface<U> {
  const rv: ObjectInterface<U> = {};

  for (const key in obj) {
    rv[key] = f(obj[key], key, obj);
  }
  return rv;
}

/**
 * @memberof object
 */
export function filterObjectF<T = any>(f: EachObjectCallbackType<T, boolean>, obj: ObjectInterface<T>):
  ObjectInterface<T> {
  const rv: Partial<ObjectInterface<T>> = {};

  for (const key in obj) {
    f(obj[key], key, obj) && (rv[key] = obj[key]);
  }
  return rv;
}
/**
 * @memberof object
 */
export function values<T>(obj: ObjectInterface<T>): T[] {
  return Object.values(obj);
}
/**
 * @memberof object
 */
export function keys<T extends ObjectInterface<T>>(obj: ObjectInterface<T>): Array<keyof T & string> {
  return Object.keys(obj);
}
/**
 * @memberof object
 */
export function headObject<T>(obj: ObjectInterface<T>): T {
  return headArray(values(obj));
}

/**
 * @memberof object
 */
export function tailObject<T>(obj: ObjectInterface<T>): T {
  return tailArray(values(obj));
}

export function takeObjectF<T extends ObjectInterface<any>>(length: number, obj: T):
  CheckPromiseType<CheckObjectType<T>,
  PromiseReturnType<ObjectInterface<CheckPromiseObjectType<T>>>,
  ObjectInterface<CheckPromiseObjectType<T>>>;
/**
 * @memberof object
 */
export function takeObjectF<T extends ObjectInterface<any>>(length: number, obj: T) {
  const objkeys = keys(obj);
  const arrLength = Math.min(length, objkeys.length);
  const objkeys2 = objkeys.slice(0, arrLength);

  return reduceArrayF((prev, cur) => {
    return exec(p => exec(c => {
      p[cur] = obj[cur];
      return p;
    }, cur), prev);
  }, {} as T | Promise<T>, objkeys2);
}