Skip to content

Commit

Permalink
Simplify omitProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
72636c committed Oct 6, 2023
1 parent 20632fe commit b657f4b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 48 deletions.
47 changes: 16 additions & 31 deletions src/serializers/omitProperties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,35 @@ import { omitProperties } from './omitProperties';

const omitPropertyNames = ['omit-prop', 'omit.prop', '', '0'];

const objBase: Readonly<Record<string, unknown>> = {
keepProp: 'Some value',
['omit-prop']: 'omit with dash',
['omit.prop']: 'omit with dot',
['']: 'omit with empty key',
['0']: 'omit number as text key',
omit: { prop: 'DO NOT omit' },
};

it('omits list of keys from object', () => {
const result = omitProperties({ ...objBase }, omitPropertyNames);

expect(result).toStrictEqual({
const createInput = (): Readonly<Record<string, unknown>> =>
Object.freeze({
keepProp: 'Some value',
['omit-prop']: 'omit with dash',
['omit.prop']: 'omit with dot',
['']: 'omit with empty key',
['0']: 'omit number as text key',
omit: { prop: 'DO NOT omit' },
});
});

it.each`
scenario | keyName
${'undefined'} | ${undefined}
${'null'} | ${null}
${'non-string'} | ${99}
`('ignores $scenario key name', ({ keyName }) => {
const result = omitProperties(
{
['99']: 'Keep key with number as text when same number provided as key',
...objBase,
},
[...omitPropertyNames, keyName],
);
it('omits list of keys from object', () => {
const input = createInput();

const result = omitProperties(input, omitPropertyNames);

expect(result).toStrictEqual({
['99']: 'Keep key with number as text when same number provided as key',
keepProp: 'Some value',
omit: { prop: 'DO NOT omit' },
});
});

it('does not alter input object', () => {
const obj = { ...objBase };
omitProperties({ ...objBase }, omitPropertyNames);
const input = createInput();

const originalInput = structuredClone(input);

omitProperties(input, omitPropertyNames);

expect(obj).toStrictEqual(objBase);
expect(input).toEqual(originalInput);
});

it.each`
Expand Down
31 changes: 14 additions & 17 deletions src/serializers/omitProperties.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
export const omitProperties = (
record: Record<string, unknown>,
keyList: string[],
): Record<string, unknown> => {
if (!record || typeof record !== 'object' || Array.isArray(record))
return record;

let reducedRecord = record;

/* eslint-disable-next-line @typescript-eslint/prefer-for-of --
* For loop is faster than `for of` and performance is preferred over readability here
**/
for (let keyIndex = 0; keyIndex < keyList.length; keyIndex++) {
const key = keyList[keyIndex];
if (typeof key !== 'string') continue;
input: unknown,
properties: string[],
): unknown => {
if (!input || typeof input !== 'object' || Array.isArray(input)) {
return input;
}

const { [key]: _, ...keepRecord } = reducedRecord;
// We can get away with a shallow clone as we only touch top-level properties.
const output: Record<PropertyKey, unknown> = {
...input,
};

reducedRecord = keepRecord;
for (const property of properties) {
// Remove the property from our shallow clone.
delete output[property];
}

return reducedRecord;
return output;
};

0 comments on commit b657f4b

Please sign in to comment.