import { isArray } from "./array";
import { isObject } from "./record";
import { isString } from "./string";

export type Nil = null | undefined;

export const isEmpty = (val: unknown): val is Nil =>
  isNil(val) ||
  (isString(val) && val.length === 0) ||
  (isArray(val) && val.length === 0) ||
  (isObject(val) && !(Object.keys(val) || val).length);

export type Maybe<T> = T | Nil;

export type MaybePromise<T> = Promise<T> | T;

export const isNull = (val: unknown): val is null => val === null;

export const isNil = (val: unknown): val is Nil =>
  val === undefined || val === null || Number.isNaN(val);

export const isSome = <T>(input: T): input is Exclude<T, Nil> => input != null;

export const isUndefined = (val: unknown): val is undefined =>
  val === undefined;
