# Filters (/docs/filters)



Overview [#overview]

Filters **remove** nodes from the value before it is serialized. They are applied in order
before any redactions. Multiple filters can be composed in the `filters` option array.

```ts
import { NullFilter, ExcludeFilter } from "vitest-snap";

const filters = [new NullFilter(), new ExcludeFilter(".internalId")];

// will filter out `null` values and exclude `internalId` prop from the received object
await expect(data).toJsonSnapshot({ filters });
```

***

UndefinedFilter [#undefinedfilter]

Removes every property whose value is `undefined`, at any depth.

<Callout>
  **Applied by default.** Pass a custom `filters` array to override.
</Callout>

Constructor [#constructor]

```ts
new UndefinedFilter();
```

Example [#example]

```ts
import { UndefinedFilter } from "vitest-snap";

const filter = new UndefinedFilter();

filter.apply({ a: 1, b: undefined, c: { d: undefined, e: 2 } });
// → { a: 1, c: { e: 2 } }
```

***

NullFilter [#nullfilter]

Removes every property whose value is `null`, at any depth.

Constructor [#constructor-1]

```ts
new NullFilter();
```

Example [#example-1]

```ts
import { NullFilter } from "vitest-snap";

const filter = new NullFilter();

filter.apply({ a: 1, b: null, c: { d: null, e: 2 } });
// → { a: 1, c: { e: 2 } }
```

Usage in snapshot [#usage-in-snapshot]

```ts
await expect(data).toJsonSnapshot({
  filters: [new NullFilter()],
});
```

***

ExcludeFilter [#excludefilter]

Removes all nodes matched by the given [selector](/docs/selectors).
All other nodes are kept.

Constructor [#constructor-2]

```ts
new ExcludeFilter(selector: Selector<T>)
```

| Parameter  | Type          | Description                                   |
| ---------- | ------------- | --------------------------------------------- |
| `selector` | `Selector<T>` | Path expression targeting the nodes to remove |

Example [#example-2]

```ts
import { ExcludeFilter } from "vitest-snap";

const filter = new ExcludeFilter(".password");

filter.apply({ id: 1, name: "Alice", password: "secret" });
// → { id: 1, name: "Alice" }
```

Nested path [#nested-path]

```ts
new ExcludeFilter(".metadata.internalId");
```

Wildcard — exclude a field from every array element [#wildcard--exclude-a-field-from-every-array-element]

```ts
new ExcludeFilter(".users[].token");
```

***

IncludeFilter [#includefilter]

Keeps **only** the nodes matched by the given [selectors](/docs/selectors). All other nodes are removed.

<Callout>
  Multiple `IncludeFilter` instances (or bare `Selector` strings placed adjacent
  to each other in the `filters` array) are automatically merged into one
  filter.
</Callout>

Constructor [#constructor-3]

```ts
new IncludeFilter(selectors: Selector<T> | Selector<T>[])
```

| Parameter   | Type                             | Description                        |
| ----------- | -------------------------------- | ---------------------------------- |
| `selectors` | `Selector<T>` or `Selector<T>[]` | Path expressions for nodes to keep |

Example — single selector [#example--single-selector]

```ts
import { IncludeFilter } from "vitest-snap";

const filter = new IncludeFilter(".name");

filter.apply({ id: 1, name: "Alice", password: "secret" });
// → { name: "Alice" }
```

Example — multiple selectors [#example--multiple-selectors]

```ts
new IncludeFilter([".id", ".name", ".email"]);
```

Example — mixed array shorthand [#example--mixed-array-shorthand]

Adjacent bare selectors in `filters` are merged automatically:

```ts
await expect(user).toJsonSnapshot({
  filters: [".id", ".name", ".email"],
  // equivalent to: [new IncludeFilter([".id", ".name", ".email"])]
});
```

<Callout>
  Adjacent bare `Selector` strings in the array are automatically merged into a
  single `IncludeFilter`, so you can mix selectors and filter instances freely.
</Callout>
