Getting Started

Setting up Types

How to define TypeScript types for your PocketBase collections.

To get the most out of pb-query, you should define TypeScript types that reflect your PocketBase collections. This allows pb-query to provide type safety and autocompletion based on your schema.

Define Your Types

Create TypeScript interfaces for each of your PocketBase collections. Make sure to include all the fields you plan to use in your queries.

types.ts
export interface User {
  id: string;
  name: string;
  email: string;
  created: Date;
  updated: Date;
}

export interface Post {
  id: string;
  title: string;
  content: string;
  author: User; // relation
  status: 'draft' | 'published';
  created: Date;
  updated: Date;
}

Supported Field Types

PocketBase FieldTypeScript Type
Plain text, Rich editor, Email, URLstring
Numbernumber
Boolboolean
Datetime, AutodateDate
JSONobject, Array<T>, or custom type
Geo PointUse the GeoPoint exposed by pb-query
RelationYour collection interface ( e.g. User)
Multiple FieldsArray of the required type ( e.g. string[], User[] )
SelectUnion of string literals ( e.g. 'draft' | 'published')

When you use a value of the wrong type in your query, TypeScript will raise an error, helping you catch mistakes early.

const query = pbQuery<Post>()
  .between('created', new Date('2023-01-01'), new Date('2023-12-31')); // ✅ Correct
const query = pbQuery<Post>()
  .equal('created', '@today'); // ✅ Correct
const query = pbQuery<Post>()
  .equal('created', '2025'); // ❌ TypeScript Error
Some field types accept macros and special modifiers, read more about them in Macros and Modifiers.

Using Types with pbQuery

When building queries, make sure to specify the type of the collection you are querying.

const { filter, sort } = pbQuery<Post>() // posts collection
  .search(['title', 'content', 'author.name'], 'footba')
  .and()
  .group((q) =>
    q.equal('status', 'published')
      .or()
      .equal('author.name', 'Sergio')
  )
  .sort(['-created'])
  .build(pb.filter);
You can set up query builders for each of your collections, learn how in Typed Query Builders.

Integration with Pocketbase Typegen

If you're already using Pocketbase Typegen you can reuse the generated types with pb-query. However, they need some adjustments.

Pocketbase Typegen produces:

  • RecordIdString for relations.
  • IsoDateString for date fields.

These types are string-based, so pb-query can't infer relations or dates.

  • Replace RecordIdString with the actual relation type. This is required, if you don't, you won't get type-checking for nested fields like author.name.
  • Replace IsoDateString with Date (optional, but recommended).
import type { PostsRecord, UsersRecord } from './types-from-pocketbase-typegen'

type UsersQuery = Omit<UsersRecord, 'created' | 'updated'> & {
  created: Date;
  updated: Date;
};

type PostsQuery = Omit<PostsRecord, 'author' | 'created' | 'updated'> & {
  author: UsersQuery;
  created: Date;
  updated: Date;
};
We recommend using the types ending in *Record like PostsRecord. However, if you need to access additional fields like collectionId inside .fields(), you can use PostsResponse instead.

Back-relations

Currently, pb-query doesn't have enough context to support back-relations properly. It would need to know a lot more about the collection schema, which complicates things quite a bit. We're working on proper back-relation support. Follow #12 for updates.

For now, you can use back-relation fields containing _via_, but they bypass type-checking:

const { filter } = pbQuery<User>()
  .like('posts_via_author.name', 'Sergio') // ⚠️ No type-checked
  .build(pb.filter);
Back-relation queries aren't type-safe. Typos like posts_via_author.titel won't be caught by TypeScript.