Skip to content

Commit

Permalink
feat(reactiveOmit): add predicate parameter (#2849)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
Alfred-Skyblue and antfu committed Mar 28, 2023
1 parent 0bde454 commit 2e297db
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
20 changes: 19 additions & 1 deletion packages/shared/reactiveOmit/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ Reactively omit fields from a reactive object.

## Usage

```js
### Basic Usage

```ts
import { reactiveOmit } from '@vueuse/core'

const obj = reactive({
Expand All @@ -21,6 +23,22 @@ const obj = reactive({
const picked = reactiveOmit(obj, 'x', 'elementX') // { y: number, elementY: number }
```

### Predicate Usage

```ts
import { reactiveOmit } from '@vueuse/core'

const obj = reactive({
bar: 'bar',
baz: 'should be omit',
foo: 'foo2',
qux: true,
})

const picked = reactiveOmit(obj, (key, value) => key === 'baz' || value === true)
// { bar: string, foo: string }
```

### Scenarios

#### Selectively passing props to child
Expand Down
24 changes: 24 additions & 0 deletions packages/shared/reactiveOmit/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,28 @@ describe('reactiveOmit', () => {
}
`)
})

it('should work with predicate', () => {
const source = reactive<TargetObject>({
foo: 'foo',
bar: 'bar',
baz: 'baz',
qux: true,
})

const state = reactiveOmit(source, (value, key) =>
key === 'bar' || key === 'baz' || value === true,
)

expect(state).toEqual({
foo: 'foo',
})

source.qux = false

expect(state).toEqual({
foo: 'foo',
qux: false,
})
})
})
18 changes: 17 additions & 1 deletion packages/shared/reactiveOmit/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { toRefs } from 'vue-demi'
import { resolveUnref } from '../resolveUnref'
import { reactiveComputed } from '../reactiveComputed'

export type ReactiveOmitPredicate<T> = (value: T[keyof T], key: keyof T) => boolean

export function reactiveOmit<T extends object, K extends keyof T>(
obj: T,
...keys: (K | K[])[]
): Omit<T, K>
export function reactiveOmit<T extends object>(
obj: T,
predicate: ReactiveOmitPredicate<T>,
): Partial<T>
/**
* Reactively omit fields from a reactive object
*
Expand All @@ -11,5 +22,10 @@ export function reactiveOmit<T extends object, K extends keyof T>(
...keys: (K | K[])[]
): Omit<T, K> {
const flatKeys = keys.flat() as K[]
return reactiveComputed<any>(() => Object.fromEntries(Object.entries(toRefs(obj)).filter(e => !flatKeys.includes(e[0] as any))))
const predicate = flatKeys[0] as unknown as ReactiveOmitPredicate<T>
return reactiveComputed<any>(() =>
typeof predicate === 'function'
? Object.fromEntries(Object.entries(toRefs(obj)).filter(([k, v]) => !predicate(resolveUnref(v) as T[K], k as K)))
: Object.fromEntries(Object.entries(toRefs(obj)).filter(e => !flatKeys.includes(e[0] as any))),
)
}

0 comments on commit 2e297db

Please sign in to comment.