Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account for non-enumerable properties in has util #1489

Merged
merged 1 commit into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Use Object.getOwnPropertyNames instead of Object.keys to account for …
…non-enumerable properties
  • Loading branch information
laurakwhit committed Jul 19, 2023
commit afeaaa170375a3df83b6325ae107df7c6a3ed675
23 changes: 14 additions & 9 deletions src/lib/utilities/has.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';

import { has, hasAnyKeys } from './has';
import { has, hasAnyProperties } from './has';

describe('has', () => {
it('returns true if an object has a key', () => {
Expand Down Expand Up @@ -50,30 +50,35 @@ describe('has', () => {
});
});

describe('hasAnyKeys', () => {
it('returns true if an object has keys', () => {
describe('hasAnyProperties', () => {
it('returns true if an object has enumerable properties', () => {
const source = { foo: 123 };
expect(hasAnyKeys(source)).toBe(true);
expect(hasAnyProperties(source)).toBe(true);
});

it('returns true if an object has non-enumerable properties', () => {
const error = new Error();
expect(hasAnyProperties(error)).toBe(true);
});

it('returns false if an object has no keys', () => {
const source = {};
expect(hasAnyKeys(source)).toBe(false);
expect(hasAnyProperties(source)).toBe(false);
});

it('should return false if given null', () => {
expect(hasAnyKeys(null)).toBe(false);
expect(hasAnyProperties(null)).toBe(false);
});

it('should return false if given undefined', () => {
expect(hasAnyKeys(undefined)).toBe(false);
expect(hasAnyProperties(undefined)).toBe(false);
});

it('should return false if given a number', () => {
expect(hasAnyKeys(3)).toBe(false);
expect(hasAnyProperties(3)).toBe(false);
});

it('should return false if given a boolean', () => {
expect(hasAnyKeys(true)).toBe(false);
expect(hasAnyProperties(true)).toBe(false);
});
});
6 changes: 3 additions & 3 deletions src/lib/utilities/has.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ export const has = <K extends Readonly<string[]>, V = unknown>(
target: unknown,
...properties: K
): target is Record<K[number], V> => {
if (!hasAnyKeys(target)) return false;
if (!hasAnyProperties(target)) return false;
for (const property of properties) {
if (!Object.prototype.hasOwnProperty.call(target, property)) return false;
}
return true;
};

export const hasAnyKeys = (
export const hasAnyProperties = (
obj: unknown,
): obj is ReturnType<typeof isObject> => {
if (!isObject(obj)) return false;
return !!Object.keys(obj).length;
return !!Object.getOwnPropertyNames(obj).length;
};
Loading