import { BIGINT, BOOLEAN, FUNCTION, NULL, NUMBER, OBJECT, STRING, SYMBOL, UNDEFINED } from './types.js'; const { isArray } = Array; export { isArray }; export const invoke = value => /** @type {Function} */ (value)(); /** * @template Value * @param {string} type * @param {Value} value * @returns {Value} */ export const reviver = (type, value) => value; /** * @template V * @typedef {[V]} Arr */ /** * @template V * @typedef {() => V} Ctx */ /** * @template T, V * @typedef {{t:T, v:V}} Obj */ /** * @template V * @typedef {V extends bigint ? BIGINT : V extends boolean ? BOOLEAN : V extends null ? NULL : V extends number ? NUMBER : V extends string ? STRING : V extends symbol ? SYMBOL : V extends undefined ? UNDEFINED : V extends object ? OBJECT : never} TypeOf */ /** * @template T, V * @param {T} t * @param {V} v * @returns {Obj} */ export const obj = (t, v) => ({t, v}); /** * @template V * @param {V} value * @returns {Ctx} */ export const bound = value => Context.bind(value); /** * @template V, T * @param {V} value * @returns {V extends Ctx ? ReturnType : V} */ export const unbound = value => ( typeof value === FUNCTION ? invoke(value) : value ); // This is needed to unlock *both* apply and construct // traps otherwise one of these might fail. // The 'use strict' directive is needed to allow // also primitive types to be bound. function Context() { 'use strict'; return this; } // TODO: is this really needed in here? // const { hasOwn } = Object; // const isConstructable = value => hasOwn(value, 'prototype'); // const isFunction = value => typeof value === FUNCTION;