# AssociatedWith() function · @imqueue/pg-sequelize

Source: https://imqueue.org/api/pg-sequelize/latest/pg-sequelize.associatedwith/
Published: 2026-08-01
Author: @imqueue maintainers (https://github.com/imqueue)
Package: @imqueue/pg-sequelize 4.2.0 — generated reference, not hand-written

Marks a field of a filter input as standing for an association rather than for a column.

**Signature:**

```typescript
export declare function AssociatedWith(cb: () => IAssociated): (target: any, key: string) => any;
```

## Parameters


| Parameter | Type | Description |
| --- | --- | --- |
| cb | () => [IAssociated](https://imqueue.org/api/pg-sequelize/latest/pg-sequelize.iassociated/) | Returns the association descriptor. |


**Returns:**

(target: any, key: string) => any

A property decorator.

## Remarks

This is what lets a caller's filter reach through a relation. `query.toWhereOptions` instantiates the input class, and any property it finds carrying one of these descriptors becomes a required `include` on the associated model, with the nested filter resolved against that model's own input class — recursively, so the nesting can go as deep as the input classes do. Without it the nested object would be treated as a column filter and produce a where clause on a column that does not exist.

Declare the field with `declare`, and do not instantiate the input class yourself. The descriptor lives on the prototype as a read-only, non-enumerable property, so a real field declaration would shadow it with `undefined` under `useDefineForClassFields` and the association would be silently ignored — and an assignment to it throws in strict mode. These classes are descriptions of a wire shape, not containers for one.

The thunk is resolved on first read rather than at decoration time, which is what makes it worth being a thunk: input classes and models routinely import each other, and a decorator body runs while those modules are still initialising, so resolving eagerly could capture `undefined` as the model. First read happens on the first query, by which point every module is loaded.

## Example


```typescript
export class PaymentListInput {
    @property(() => `number[] | ${FilterInput.name}`, true)
    declare public amount?: number[] | FilterInput;

    @property('PaymentTypeListInput', true)
    @AssociatedWith(() => ({
        model: PaymentType,
        input: PaymentTypeListInput,
    }))
    declare public paymentType?: PaymentTypeListInput;
}

// A filter of { paymentType: { name: 'card' } } now becomes a required join on
// PaymentType with the name filter applied there.
const options = query.toWhereOptions(filter, PaymentListInput);
```

