Skip to content

Commit

Permalink
fjl - Cleaned up some implementations, and removed some deprecated me…
Browse files Browse the repository at this point in the history
…mbers.

- Added 'hasOwn' to 'ObjectStatics' type.
- Updated 'hasOwnProperty' impl. to just be, the flipped, 'native.hasOwn' method, if it exists.
- Updated 'fromAssocList' method to use the native one ('Object.fromEntries'), if it exists.
- Added some notes related to some refactors.
  • Loading branch information
elycruz committed Dec 17, 2023
1 parent 586ffff commit 520efcf
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 272 deletions.
9 changes: 3 additions & 6 deletions packages/fjl/src/object/assignDeep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const
// If property being visited is not settable, skip it
if (propDescriptor && (
propDescriptor.writable === false || (
propDescriptor.writable === undefined &&
!propDescriptor.writable &&
!propDescriptor.set
)
)) {
Expand All @@ -28,13 +28,10 @@ export const
value = obj[key];

// If LHV is not a primitive, and RHV contains enumerables then values are assignable
if (!isPrimitive(existingValue) &&
containsEnumerables(value)
) {
if (!isPrimitive(existingValue) && containsEnumerables(value))
assignDeep(existingValue, value);
} else {
else
agg[key] = value;
}

return agg;
}, topAgg);
Expand Down
8 changes: 3 additions & 5 deletions packages/fjl/src/object/assocList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const
/**
* Returns an associated list from given object.
*/
toAssocList = <T>(obj: T): [keyof T, any][] => Object.entries(obj) as [keyof T, any][],
toAssocList = Object.entries,

/**
* @deprecated Not to many algorithms require this kind of
Expand All @@ -39,10 +39,8 @@ export const
/**
* From associated list to zero object.
*/
fromAssocList = (xs, zero = {}) => foldl((agg, [key, value]) => {
agg[key] = value;
return agg;
}, zero, xs),
fromAssocList = Object.fromEntries ?? ((xs, zero = {}) => foldl((agg, [key, value]) => (
agg[key] = value, agg), zero, xs)),

/**
* @deprecated Method is too specific - Define functionality/method
Expand Down
145 changes: 14 additions & 131 deletions packages/fjl/src/object/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

import {typeOf} from './typeOf';
import {instanceOf, keys} from '../platform/object';
import {hasOwnProperty, instanceOf, keys} from '../platform/object';
import {isset} from './isset';
import {Constructable, TypeRef, Unary} from "../types";

Expand Down Expand Up @@ -70,8 +70,8 @@ export const
isFunction = (x: any): boolean => instanceOf(Function, x),

/**
* @deprecated Use `instanceOf` instead (checks both value's
* constructor, against passed in type, else `instanceof` check).
* @deprecated Use `instanceOf` instead (performs equality check on constructors
* and, ultimately, performs `instanceof` check, if constructors are not the same).
*
* Strict type checker. Checks if given value is a direct instance of given type; E.g.,
* @example
Expand All @@ -88,21 +88,6 @@ export const
*/
isType = (type: TypeRef | any, obj: any): boolean => typeOf(obj) === toTypeRefName(type),

/**
* @deprecated Use `$instanceOf` instead (checks both value's
* constructor, against passed in type, else `instanceof` check).
*/
$isType = (type: TypeRef | any) =>
(obj: any): boolean => isType(type, obj),

/**
* @deprecated Use `instanceOf` instead (checks both value's
* constructor, against passed in type, else `instanceof` check).
*
* Synonym for `isType` (or just a more accurate name for `isType`).
*/
isStrictly = isType,

/**
* Checks if given value contains a constructor equal to one of the passed in ones,
* or if it is an instance of one of the passed in ones.
Expand All @@ -124,6 +109,8 @@ export const
* isInstanceOf([], Array) === true
* isInstanceOf({}, Object) === true
* ```
*
* @todo consolidate implementation into `instanceOf`.
*/
isInstanceOf = (x: any, ...types: Constructable[]): boolean =>
types.some(t => instanceOf(t, x)),
Expand Down Expand Up @@ -153,20 +140,13 @@ export const
*/
isOfType = (type, x) => isType(type, x) || instanceOf(type, x),

/**
* @deprecated Use `isInstanceOf`.
*
* Synonym for `isInstanceOf` (or just a more accurate name).
*/
isLoosely = isInstanceOf,

/**
* Checks if `value` is an es2015 (user defined) `class`.
*/
isClass = (x: any): boolean => x && _classPrefixRegex.test((x + '').substring(0, 11)),

/**
* Returns a boolean depicting whether a value is callable or not.
* Returns a boolean denoting whether a value is callable or not.
*/
isCallable = (x: any): boolean => isFunction(x) && !isClass(x),

Expand All @@ -182,11 +162,12 @@ export const

/**
* Checks if value is a boolean.
* @todo Replace instances of `isset(...)` with optional chaining (since it is now in the spec).
*/
isBoolean = x => isset(x) && x.constructor === Boolean,

/**
* Checks if value is a number, and/or a bigint, and not `NaN`.
* Checks if value is not `NaN`, and is a number, and/or a bigint.
*
* ```typescript
* isNumber(99) === true;
Expand Down Expand Up @@ -216,34 +197,6 @@ export const
isString = x =>
isset(x) && x.constructor === String,

/**
* @deprecated Perform `instanceof` check instead.
*
* Checks whether value is of `Map` or not.
*/
isMap = x => isset(x) && x instanceof Map,

/**
* @deprecated Perform `instanceof` check instead.
*
* Checks whether value is of `Set` or not.
*/
isSet = $isType(Set.name) as Unary<any, boolean>,

/**
* @deprecated Perform `instanceof` check instead.
*
* Checks whether value is of `WeakMap` or not.
*/
isWeakMap = $isType(WeakMap.name) as Unary<any, boolean>,

/**
* @deprecated Perform `instanceof` check instead.
*
* Checks whether value is of `WeakSet` or not.
*/
isWeakSet = $isType(WeakSet.name) as Unary<any, boolean>,

/**
* Checks if value is undefined.
*/
Expand Down Expand Up @@ -272,48 +225,22 @@ export const
},

/**
* Checks if given value is not `null`, not `undefined`, and is a constructable primitive (e.g., instance/literal of
* one of `String`, `Boolean`, `Number`, `BigInt`, and/or, `Symbol`);
* Checks if given value is not `null`, not `undefined`, and is a constructable primitive (
* e.g., instance/literal of one of `String`, `Boolean`, `Number`, `BigInt`, and/or, `Symbol`);
*/
isConstructablePrimitive = (x: any): boolean =>
!isset(x) ? false :
_primitive_constructors
.some(type => instanceOf(type, x)),

/**
* @deprecated Use `isConstructablePrimitive` instead.
*/
isUsableImmutablePrimitive = isConstructablePrimitive,

/**
* @deprecated check length directly and/or create a new method for
* the purpose; e.g., `const notLength = x => !(x?.length)`, etc.
*
* Checks if !length.
*/
isEmptyList = (x: any): boolean => !(x?.length),

/**
* Checks if object contains enumerable properties or not.
* @todo requires tests.
* @todo write tests.
*/
containsEnumerables = (x: any): boolean => isset(x) && keys(x).length > 0,

/**
* @deprecated Use `containsEnumerables`.
*/
isEmptyObject = containsEnumerables,

/**
* @deprecated Check values directly.
*
* Checks if collection is empty or not (Map, WeakMap, WeakSet, Set etc.).
*/
isEmptyCollection = (x: { readonly size: number }): boolean => x.size === 0,

/**
* @deprecated Check values/value type states directly.
*
* Checks if passed in value is falsy, an empty array,
* an empty es6 collection object (Map, Set, etc.),
* and/or, contains no enumerable properties/is an empty object (of
Expand All @@ -323,9 +250,7 @@ export const
// if '', `0`/`0n`, `null`, `undefined`, `NaN`, or `false` then value is empty
if (!x) return true;

const {constructor} = x;

switch (constructor) {
switch (x.constructor) {
// If is a constructable primitive, it's not empty (at this point)
case String:
case Number:
Expand All @@ -336,52 +261,10 @@ export const
default:
if (isInstanceOf(x, Map, Set, WeakSet, WeakMap)) return !x.size;

if (x?.length) return false;
if (x.length) return false;

// Else check if object doesn't contain enumerable properties
return !keys(x).length;
}
},

/**
* @deprecated - Use `isInstanceOf` method.
*
* Checks to see if `x` is of one of the given type refs; Strict
* type check (not-instanceof check).
*
* @todo write tests for this function.
*/
isOneOf = (x: any, ...types: any): boolean => {
const typeName = typeOf(x);
return toTypeRefNames(types).some(name => typeName === name);
},

/**
* @deprecated Use `isInstanceOf` method.
*
* Checks if given value is strictly one of given types.
*/
isStrictlyOneOf = isOneOf,

/**
* @deprecated Use `isInstanceOf` instead.
*
* Checks if given value is either strictly one of given types or is
* an `instanceof` one of given types.
*/
isLooselyOneOf = (x: any, ...types: any): boolean =>
types.some(type => isType(type, x) || instanceOf(x, type)),

/**
* @deprecated Use `isInstanceOf`.
*/
instanceOfOne = isInstanceOf,

/**
* @deprecated Checks types directly.
*
* Checks if value qualifies (has `map` method) as a functor.
*/
isFunctor = (x: any): boolean => isset(x) && isFunction(x.map)

}
;
8 changes: 3 additions & 5 deletions packages/fjl/src/object/typeOf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@ const _NaN = 'NaN',
* `undefined` and 'Null' for `null`.
*/
export function typeOf(value: any): string {
let retVal;
if (value === undefined) {
retVal = _Undefined;
return _Undefined;
} else if (value === null) {
retVal = _Null;
return _Null;
} else {
const {name: constructorName} = value.constructor;
retVal = (
return (
constructorName === Number.name ||
constructorName === BigInt.name
) && Number.isNaN(value) ?
_NaN : constructorName;
}
return retVal;
}
42 changes: 21 additions & 21 deletions packages/fjl/src/platform/object/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,6 @@ export const
// @todo We shouldn' be returning these directly.
{assign, keys} = Object,

/**
* @todo Method should take object as first argument.
*/
instanceOf = (X: Constructable, x): boolean =>
isset(x) && x.constructor === X || x instanceof X, // @todo remove null check (isset) here (in future release).

$instanceOf = (X: Constructable) => (x): boolean => instanceOf(X, x),

/**
* @todo Method should take object as first argument.
*/
hasOwnProperty = <T extends object>(key: string | PropertyKey, x: T): boolean =>
// @note `Object.hasOwn` cannot be used here until it is more broadly
// adopted (until node v24+ release etc.).
isset(x) && Object.prototype.hasOwnProperty.call(x, key) // @todo shouldn't be checking for null/undefined here
,

$hasOwnProperty = <T extends object>(key: string | PropertyKey) =>
(x: T): boolean => hasOwnProperty(key, x),

/**
* Contains all the static functions from `Object` but curried and flipped;
* Methods that only take one parameter, or only 'rest' args, are exported as is.
Expand Down Expand Up @@ -86,6 +66,26 @@ export const
break;
}
return agg;
}, {}) as ObjectStatics
}, {}) as ObjectStatics,

/**
* @todo Method should take object as first argument.
*/
instanceOf = (X: Constructable, x): boolean =>
isset(x) && x.constructor === X || x instanceof X, // @todo remove null check (isset) here (in future release).

$instanceOf = (X: Constructable) => (x): boolean => instanceOf(X, x),

/**
* @todo Method should take object as first argument.
*/
hasOwnProperty = native.hasOwn ?? (<T extends object>(key: string | PropertyKey, x: T): boolean =>
// @note `Object.hasOwn` cannot be used here until it is more broadly
// adopted (until node v24+ release etc.).
isset(x) && Object.prototype.hasOwnProperty.call(x, key)) // @todo shouldn't be checking for null/undefined here
,

$hasOwnProperty = <T extends object>(key: string | PropertyKey) =>
(x: T): boolean => hasOwnProperty(key, x)

;
3 changes: 2 additions & 1 deletion packages/fjl/src/types/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type CreateFunc = (pdm: PropertyDescriptorMap, applicand: any) => any;

export type IsFunc = (Type: any, value: any) => boolean;

// @todo Need to added es > es6 methods below.
// @todo Need to add es > es6 methods below.
export interface ObjectStatics {
assign: (...xs: any[]) => any;
create: CreateFunc;
Expand All @@ -22,6 +22,7 @@ export interface ObjectStatics {
getOwnPropertyNames: (x: any) => string[];
getOwnPropertySymbols: (x: any) => symbol[];
getPrototypeOf: (x: any) => object | null;
hasOwn: (propName: string | PropertyKey, x: any) => boolean;
is: IsFunc;
isExtensible: (x: any) => boolean;
isFrozen: (x: any) => boolean;
Expand Down
16 changes: 0 additions & 16 deletions packages/fjl/tests/list/test-isEmpty.ts

This file was deleted.

Loading

0 comments on commit 520efcf

Please sign in to comment.