Skip to content

Commit

Permalink
feat(utils): shake
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Jul 25, 2023
1 parent 435a9c4 commit b5d37de
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/utils/__tests__/shake.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @file Type Tests - shake
* @module tutils/utils/tests/unit-d/shake
*/

import type { Shake } from '#src/types'
import type testSubject from '../shake'

describe('unit-d:utils/shake', () => {
it('should return Shake<T, F>', () => {
// Arrange
type T = { x: number; y: null }
type F = null
type Expect = Shake<T, F>

// Expect
expectTypeOf<typeof testSubject<T, F>>().returns.toEqualTypeOf<Expect>()
})
})
23 changes: 23 additions & 0 deletions src/utils/__tests__/shake.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file Unit Tests - shake
* @module tutils/utils/tests/unit/shake
*/

import testSubject from '../shake'

describe('unit:utils/shake', () => {
let obj: { x: number; y: undefined }

beforeAll(() => {
obj = { x: faker.number.int(), y: undefined }
})

it('should return filtered object', () => {
// Act
const result = testSubject(obj)

// Expect
expect(result).to.equal(obj).and.have.property('x', obj.x)
expect(result).to.not.have.property('y')
})
})
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export { default as regexp } from './regexp'
export { default as reverse } from './reverse'
export { default as segment } from './segment'
export { default as select } from './select'
export { default as shake } from './shake'
export { default as sift } from './sift'
export { default as sort } from './sort'
export { default as split } from './split'
Expand Down
45 changes: 45 additions & 0 deletions src/utils/shake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @file Utilities - shake
* @module tutils/utils/shake
*/

import type { Fn, ObjectCurly, Shake, Values } from '#src/types'
import cast from './cast'
import isUndefined from './is-undefined'
import properties from './properties'

/**
* Remove properties from an object where the key-value meets a given `filter`
* condition. The initial target object **will** be modified.
*
* All `undefined` properties will be removed if a `filter` is not provided.
*
* Inherited properties will not be removed.
*
* **Note**: TypeScript does not track inheritance. The return type may differ
* from the actual return value when target objects contain inherited properties
* (e.g. `Map`, `Set`) that meet the `filter` condition. In such cases, the
* return type will have less properties than present on the return value.
*
* @see {@linkcode Shake}
*
* @todo examples
*
* @template T - Object to filter
* @template F - Key value filter
*
* @param {T} obj - Object to filter
* @param {Fn<[Values<T>[number]], boolean>} [filter=isUndefined] - Value filter
* @return {Shake<T, F>} Filtered object
*/
const shake = <T extends ObjectCurly, F = undefined>(
obj: T,
filter: Fn<[Values<T>[number]], boolean> = isUndefined
): Shake<T, F> => {
return properties(obj).reduce<Shake<T, F>>((acc, key) => {
filter(obj[cast<keyof typeof obj>(key)]) && Reflect.deleteProperty(acc, key)
return acc
}, cast(obj))
}

export default shake

0 comments on commit b5d37de

Please sign in to comment.