tiinvo
Version:
A library of types and utilities for your TypeScript and JavaScript projects
327 lines (326 loc) • 7.17 kB
JavaScript
//#region guards
/**
* Returns true if `x` is of type `object` and not null
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.guard({}); // true
* Obj.guard(null); // false
* ```
*
* @param x the object
* @returns
* - true if x is object and not null
* - false otherwise
* @group Guardables
* @since 4.0.0
*/
export const guard = (x) => typeof (x) === 'object' && !!x;
/**
* Returns a guard which checks if a value `v` implements a shape `s`
*
* @example
* ```ts
* import { Obj, Str, Num, Bool } from 'tiinvo';
*
* const isABC = Obj.guardOf({
* a: Str.guard,
* b: Num.guard,
* c: Bool.guard
* });
*
* isABC({ a: `foo`, b: 1, c: true }); // true
* isABC({ a: `foo`, b: false, c: 1 }); // false
*
* // you can also set recursive shapes, or directly more comples ones
*
* const isUser = Obj.guardOf({
* name: Str.guard,
* surname: Str.guard,
* age: Num.guard,
* billing: {
* address: Str.guard,
* city: Str.guard,
* }
* })
*
* isUser(10) // false
* isUser({}) // false
* isUser({
* name: 'john',
* surname: 'doe',
* age: 44,
* }) // false
* isUser({
* name: 'john',
* surname: 'doe',
* age: 44,
* billing: {
*
* }
* }) // false
* isUser({
* name: 'john',
* surname: 'doe',
* age: 44,
* billing: {
* address: '',
* }
* }) // false
* isUser({
* name: 'john',
* surname: 'doe',
* age: 44,
* billing: {
* address: 'some address',
* city: 'some city',
* }
* }) // true
* ```
*
* @template A the guard structure
* @param s the struct which represents the guarded type
* @returns the `Guardable<A>` if s is an `object`, otherwise it throws a `TypeError`
* @group Guardables
* @since 4.0.0
*/
export const guardOf = (s) => {
if (!guard(s)) {
throw new TypeError("Invalid Struct guard, expected an object (GuardsFromStruct<a>), got " + typeof s);
}
return (v) => {
if (!guard(v)) {
return false;
}
const keys = Object.keys(s);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const currentvalue = v[key];
const currentguard = s[key];
const case1 = guard(currentguard) && guardOf(currentguard)(currentvalue);
const case2 = typeof currentguard === 'function' && currentguard(currentvalue);
if (!case1 && !case2) {
return false;
}
}
return true;
};
};
export function hasKey(k, o) {
if (arguments.length === 2) {
return guard(o) && o.hasOwnProperty(k);
}
return (b) => guard(b) && b.hasOwnProperty(k);
}
;
export function hasKeyOf(k, g, o) {
const og = (k, g, o) => guard(o) && o.hasOwnProperty(k) && g(o[k]);
if (!!k && !!g && !!o) {
return og(k, g, o);
}
return (o) => og(k, g, o);
}
//#endregion
//#region native methods
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a new object.
*
* **important**: This will not mutate any object, it will always return a new one instead.
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* const a = { a: 1, b: 2 };
* const b = { b: 3, c: 4 };
* const c = { c: 5, d: 6 };
*
* Obj.assign(a, b, c);
* // { a: 1, b: 3, c: 5, d: 6 }
* ```
*
* @returns The target object
* @group Natives
* @since 4.0.0
*/
export const assign = (x, ...b) => Object.assign({}, x, ...b);
/**
* Returns an array of key/values of the enumerable properties of an object `o`
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.entries({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ]
* ```
*
* @template O the object's type
* @param o the object
* @returns the entries
* @group Natives
* @since 4.0.0
*/
export const entries = Object.entries;
/**
* Prevents the modification of existing property attributes and values,
* and prevents the addition of new properties.
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* const a = { a: 1, b: 2 };
* Obj.freeze(a);
* a.a = 100; // throws
* ```
*
* @group Natives
* @since 4.0.0
*/
export const freeze = Object.freeze;
/**
* Returns an object created by key-value entries for properties and methods
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.fromEntries([ ['a', 1], ['b', 2] ]) // { a: 1, b: 2 }
* ```
*
* @param entries the entries
* @returns
* @group Natives
* @since 4.0.0
*/
export const fromEntries = Object.fromEntries;
/**
* Gets a property `a` from an object `b` and returns a `Option.t<c>`
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* const get = Obj.get(`foo`);
*
* get({ foo: `bar` }); // some<`bar`>
* get({}); // none
* ```
*
* @param a the property to get
* @returns
* @group Natives
* @since 4.0.0
*/
export const get = (a) => (b) => hasKey(a)(b) ? b[a] : null;
export function omit(k, o) {
const fn = (x, y) => {
const omitted = {};
const ownedkeys = keys(y);
for (let index = 0; index < ownedkeys.length; index++) {
const key = ownedkeys[index];
if (!x.includes(key)) {
omitted[key] = y[key];
}
}
return omitted;
};
if (Array.isArray(k) && !!o) {
return fn(k, o);
}
return (b) => fn(k, b);
}
;
export function pick(keys, o) {
const fn = (x, y) => {
const o = {};
for (let i = 0; i < x.length; i++) {
const key = x[i];
if (hasKey(key)(y)) {
o[key] = y[key];
}
}
return o;
};
if (Array.isArray(keys) && !!o) {
return fn(keys, o);
}
return (b) => fn(keys, b);
}
//#endregion
//#region mappables
/**
* Maps an object `a` to a value `b`
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.map(Object.keys)({ a: 10, b: 20 }); // ['a', 'b']
* Obj.map((x: Record<string, number>) => x.a ?? 0)({ a: 10 }); // 10
* Obj.map((x: Record<string, number>) => x.a ?? 0)({ b: 10 }); // 0
* ```
*
* @param a
* @returns
* @since 4.0.0
**/
export const map = (m) => (a) => guard(a) ? m(a) : null;
/**
* Returns the names of the enumerable string properties and methods of an object.
*
* @example
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.keys({ a: 10, b: 20 }) // ['a', 'b']
* ```
*
* @since 4.0.0
*/
export const keys = Object.keys;
/**
* Returns an object size
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.size({ a: 1, b: 2 }) // 2
* Obj.size({}) // 0
* ```
*
* @param x the object
* @returns the size (count of keys) of the object
* @since 4.0.0
**/
export const size = (x) => keys(x).length;
/**
* Returns an array of values of the enumerable properties of an object
*
* @example
*
* ```ts
* import { Obj } from 'tiinvo';
*
* Obj.values({ a: 1, b: 2 }) // [1, 2]
* Obj.values({}) // []
* ```
*
* @param a
* @returns
* @since 4.0.0
**/
export const values = Object.values;
;
//#endregion