Skip to content

Commit

Permalink
feat(utilities): add omitKeysFromObject utility function (#700)
Browse files Browse the repository at this point in the history
* feat(utilities): add omitKeysFromObject utility function

---------

Co-authored-by: Aura <[email protected]>
  • Loading branch information
favna and kyranet authored Dec 28, 2023
1 parent 1f92fd2 commit eccf9f6
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
"rules": {
"@typescript-eslint/member-ordering": "off"
}
},
{
"files": ["packages/utilities/src/lib/omitKeysFromObject.ts"],
"rules": {
"@typescript-eslint/ban-types": "off"
}
}
]
}
10 changes: 10 additions & 0 deletions packages/utilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,16 @@
"default": "./dist/cjs/lib/objectValues.cjs"
}
},
"./omitKeysFromObject": {
"import": {
"types": "./dist/esm/lib/omitKeysFromObject.d.mts",
"default": "./dist/esm/lib/omitKeysFromObject.mjs"
},
"require": {
"types": "./dist/cjs/lib/omitKeysFromObject.d.ts",
"default": "./dist/cjs/lib/omitKeysFromObject.cjs"
}
},
"./parseURL": {
"import": {
"types": "./dist/esm/lib/tryParseURL.d.mts",
Expand Down
1 change: 1 addition & 0 deletions packages/utilities/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export * from './lib/objectEntries';
export * from './lib/objectKeys';
export * from './lib/objectToTuples';
export * from './lib/objectValues';
export * from './lib/omitKeysFromObject';
export * from './lib/partition';
export * from './lib/pickRandom';
export * from './lib/poll';
Expand Down
24 changes: 24 additions & 0 deletions packages/utilities/src/lib/omitKeysFromObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { deepClone } from './deepClone';

/**
* Clones the source object using {@link deepClone} then deletes the specified keys with {@link Reflect.deleteProperty}
*
* @template TO - The object type.
* @template KTO - The keys of the object type.
*
* @param source - The input object.
* @param keys - The keys to omit from the object.
* @returns A new object without the specified keys.
*/
export function omitKeysFromObject<Object extends object, ObjectKeys extends keyof Object>(
source: Object,
...keys: readonly ObjectKeys[]
): Omit<Object, ObjectKeys> {
const clone = deepClone(source);

for (const key of keys) {
Reflect.deleteProperty(clone, key);
}

return clone;
}
55 changes: 55 additions & 0 deletions packages/utilities/tests/omitKeysFromObject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { omitKeysFromObject } from '../src/lib/omitKeysFromObject';

describe('omitKeysFromObject', () => {
test('GIVEN object and keys THEN returns object without specified keys', () => {
const source = { name: 'John', age: 30, city: 'New York' };
const result = omitKeysFromObject(source, 'age', 'city');
expect(result).toEqual({ name: 'John' });
});

test('GIVEN object and no keys THEN returns the same object', () => {
const source = { name: 'John', age: 30, city: 'New York' };
const result = omitKeysFromObject(source);
expect(result).toEqual(source);
});

test('GIVEN empty object and keys THEN returns empty object', () => {
const source = {};
// @ts-expect-error Testing invalid input
const result = omitKeysFromObject(source, 'age', 'city');
expect(result).toEqual({});
});

test('GIVEN an object with ES objects THEN returns object without specified keys', () => {
const source = {
one: new Map(),
two: new Set(),
three: new Date(),
four: new Uint8Array(),
five: new Error(),
six: new RegExp(''),
seven: []
};
const result = omitKeysFromObject(source, 'one', 'two', 'three', 'four', 'five', 'six', 'seven');
expect(result).toEqual({});
});

test('GIVEN keys as array THEN removes keys', () => {
const source = { name: 'John', age: 30, city: 'New York' };
// @ts-expect-error spreading Arrays gives "string" instead of "keyof T"
const result = omitKeysFromObject(source, ...['age', 'city']);
expect(result).toEqual({ name: 'John' });
});

test("GIVEN any source object THEN validates that the result isn't identical to the source", () => {
const source = { name: 'John', age: 30, city: 'New York' };
const result = omitKeysFromObject(source);
expect(result).not.toBe(source);
});

test("GIVEN any source object THEN validates that the source isn't modified", () => {
const source = { name: 'John', age: 30, city: 'New York' };
omitKeysFromObject(source);
expect(source).toEqual({ name: 'John', age: 30, city: 'New York' });
});
});

0 comments on commit eccf9f6

Please sign in to comment.