fix: Fix circular dependencies in isJSONArray, isJSONObject, and isJSONValue

This commit is contained in:
raon0211 2024-10-16 09:59:58 +09:00
parent 307b362afc
commit 904ca1a2b4
7 changed files with 111 additions and 117 deletions

View File

@ -7,9 +7,7 @@ export { isEqualWith } from './isEqualWith.ts';
export { isError } from './isError.ts';
export { isFile } from './isFile.ts';
export { isFunction } from './isFunction.ts';
export { isJSONArray } from './isJSONArray.ts';
export { isJSONObject } from './isJSONObject.ts';
export { isJSONValue } from './isJSONValue.ts';
export { isJSONArray, isJSONObject, isJSONValue } from './isJSONValue.ts';
export { isLength } from './isLength.ts';
export { isMap } from './isMap.ts';
export { isNil } from './isNil.ts';

View File

@ -1,21 +0,0 @@
import { describe, expect, it } from 'vitest';
import { isJSONArray } from './isJSONArray.ts';
describe('isJSONArray', () => {
it('should return true for valid JSON arrays', () => {
expect(isJSONArray([1, 2, 3])).toBe(true);
expect(isJSONArray(['string', null, true])).toBe(true);
expect(isJSONArray([{ key: 'value' }, [1, 2], null])).toBe(true);
expect(isJSONArray([])).toBe(true);
});
it('should return false for invalid JSON arrays', () => {
expect(isJSONArray('not an array')).toBe(false);
expect(isJSONArray(123)).toBe(false);
expect(isJSONArray(null)).toBe(false);
expect(isJSONArray(undefined)).toBe(false);
expect(isJSONArray({})).toBe(false);
expect(isJSONArray([1, 2, () => {}])).toBe(false);
expect(isJSONArray([1, 2, new Date()])).toBe(false);
});
});

View File

@ -1,23 +0,0 @@
import { isJSONValue } from './isJSONValue.ts';
/**
* Checks if a given value is a valid JSON array.
*
* A valid JSON array is defined as an array where all items are valid JSON values.
*
* @param {unknown} value - The value to check.
* @returns {value is any[]} - True if the value is a valid JSON array, otherwise false.
*
* @example
* console.log(isJSONArray([1, 2, 3])); // true
* console.log(isJSONArray(["string", null, true])); // true
* console.log(isJSONArray([1, 2, () => {}])); // false
* console.log(isJSONArray("not an array")); // false
*/
export function isJSONArray(value: unknown): value is any[] {
if (!Array.isArray(value)) {
return false;
}
return value.every(item => isJSONValue(item));
}

View File

@ -1,29 +0,0 @@
import { describe, expect, it } from 'vitest';
import { isJSONObject } from './isJSONObject.ts';
describe('isJSONObject', () => {
it('isJSONObject should return true for valid JSON objects', () => {
expect(isJSONObject({ a: 1, b: 'es-toolkit' })).toBe(true);
expect(isJSONObject({})).toBe(true);
expect(isJSONObject({ nested: { boolean: true, array: [1, 2, 3], string: 'test', null: null } })).toBe(true);
});
it('isJSONObject should return false for not valid value', () => {
expect(isJSONObject(null)).toBe(false);
expect(isJSONObject(undefined)).toBe(false);
expect(isJSONObject('string')).toBe(false);
expect(isJSONObject(123)).toBe(false);
expect(isJSONObject(true)).toBe(false);
expect(isJSONObject([1, 2, 3])).toBe(false);
expect(isJSONObject({ date: new Date() })).toBe(false);
expect(isJSONObject({ func: () => {} })).toBe(false);
expect(isJSONObject({ regexp: /test/ })).toBe(false);
expect(isJSONObject({ undefinedProperty: undefined })).toBe(false);
expect(isJSONObject({ symbolProperty: Symbol('test') })).toBe(false);
expect(isJSONObject({ nested: { a: function* () {} } })).toBe(false);
});
it('isJSONObject should return false when key is not a string', () => {
expect(isJSONObject({ [Symbol('a')]: 'a' })).toBe(false);
});
});

View File

@ -1,38 +0,0 @@
import { isJSONValue } from './isJSONValue.ts';
import { isPlainObject } from './isPlainObject.ts';
/**
* Checks if a value is a JSON object.
*
* A valid JSON object is defined as an object with string keys and valid JSON values.
*
* @param {unknown} obj The value to check.
* @returns {obj is Record<string, any>} True if `obj` is a JSON object, false otherwise.
*
* @example
* isJSONObject({ nested: { boolean: true, array: [1, 2, 3], string: 'test', null: null } }); // true
* isJSONObject({ regexp: /test/ }); // false
* isJSONObject(123); // false
*/
export function isJSONObject(obj: unknown): obj is Record<string, any> {
if (!isPlainObject(obj)) {
return false;
}
const keys = Reflect.ownKeys(obj);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = obj[key];
if (typeof key !== 'string') {
return false;
}
if (!isJSONValue(value)) {
return false;
}
}
return true;
}

View File

@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { isJSONValue } from './isJSONValue.ts';
import { isJSONArray, isJSONObject, isJSONValue } from './isJSONValue.ts';
describe('isJSONValue', () => {
it('should return true for null', () => {
@ -34,3 +34,49 @@ describe('isJSONValue', () => {
expect(isJSONValue(Symbol('symbol'))).toBe(false);
});
});
describe('isJSONArray', () => {
it('should return true for valid JSON arrays', () => {
expect(isJSONArray([1, 2, 3])).toBe(true);
expect(isJSONArray(['string', null, true])).toBe(true);
expect(isJSONArray([{ key: 'value' }, [1, 2], null])).toBe(true);
expect(isJSONArray([])).toBe(true);
});
it('should return false for invalid JSON arrays', () => {
expect(isJSONArray('not an array')).toBe(false);
expect(isJSONArray(123)).toBe(false);
expect(isJSONArray(null)).toBe(false);
expect(isJSONArray(undefined)).toBe(false);
expect(isJSONArray({})).toBe(false);
expect(isJSONArray([1, 2, () => {}])).toBe(false);
expect(isJSONArray([1, 2, new Date()])).toBe(false);
});
});
describe('isJSONObject', () => {
it('isJSONObject should return true for valid JSON objects', () => {
expect(isJSONObject({ a: 1, b: 'es-toolkit' })).toBe(true);
expect(isJSONObject({})).toBe(true);
expect(isJSONObject({ nested: { boolean: true, array: [1, 2, 3], string: 'test', null: null } })).toBe(true);
});
it('isJSONObject should return false for not valid value', () => {
expect(isJSONObject(null)).toBe(false);
expect(isJSONObject(undefined)).toBe(false);
expect(isJSONObject('string')).toBe(false);
expect(isJSONObject(123)).toBe(false);
expect(isJSONObject(true)).toBe(false);
expect(isJSONObject([1, 2, 3])).toBe(false);
expect(isJSONObject({ date: new Date() })).toBe(false);
expect(isJSONObject({ func: () => {} })).toBe(false);
expect(isJSONObject({ regexp: /test/ })).toBe(false);
expect(isJSONObject({ undefinedProperty: undefined })).toBe(false);
expect(isJSONObject({ symbolProperty: Symbol('test') })).toBe(false);
expect(isJSONObject({ nested: { a: function* () {} } })).toBe(false);
});
it('isJSONObject should return false when key is not a string', () => {
expect(isJSONObject({ [Symbol('a')]: 'a' })).toBe(false);
});
});

View File

@ -1,5 +1,8 @@
import { isJSONArray } from './isJSONArray.ts';
import { isJSONObject } from './isJSONObject.ts';
/**
* The functions isJSONValue, isJSONArray, and isJSONObject are grouped in this file
* to prevent any circular dependency issues.
*/
import { isPlainObject } from './isPlainObject.ts';
/**
* Checks if a given value is a valid JSON value.
@ -40,3 +43,61 @@ export function isJSONValue(value: unknown): value is Record<string, any> | any[
}
}
}
/**
* Checks if a given value is a valid JSON array.
*
* A valid JSON array is defined as an array where all items are valid JSON values.
*
* @param {unknown} value - The value to check.
* @returns {value is any[]} - True if the value is a valid JSON array, otherwise false.
*
* @example
* console.log(isJSONArray([1, 2, 3])); // true
* console.log(isJSONArray(["string", null, true])); // true
* console.log(isJSONArray([1, 2, () => {}])); // false
* console.log(isJSONArray("not an array")); // false
*/
export function isJSONArray(value: unknown): value is any[] {
if (!Array.isArray(value)) {
return false;
}
return value.every(item => isJSONValue(item));
}
/**
* Checks if a value is a JSON object.
*
* A valid JSON object is defined as an object with string keys and valid JSON values.
*
* @param {unknown} obj The value to check.
* @returns {obj is Record<string, any>} True if `obj` is a JSON object, false otherwise.
*
* @example
* isJSONObject({ nested: { boolean: true, array: [1, 2, 3], string: 'test', null: null } }); // true
* isJSONObject({ regexp: /test/ }); // false
* isJSONObject(123); // false
*/
export function isJSONObject(obj: unknown): obj is Record<string, any> {
if (!isPlainObject(obj)) {
return false;
}
const keys = Reflect.ownKeys(obj);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = obj[key];
if (typeof key !== 'string') {
return false;
}
if (!isJSONValue(value)) {
return false;
}
}
return true;
}