Lit Query is written in TypeScript and reuses TanStack Query Core's type system. The most important rule is the same as every other adapter: give your query and mutation functions well-defined return types, and the result accessors will infer from them.
Set useDefineForClassFields to false in your tsconfig.json so reactive properties initialized as class fields keep triggering updates. See Requirements for details.
import { LitElement } from 'lit'
import { createQueryController } from '@tanstack/lit-query'
type Todo = {
id: number
title: string
}
async function fetchTodos(): Promise<Todo[]> {
const response = await fetch('/api/todos')
if (!response.ok) throw new Error('Failed to fetch todos')
return response.json() as Promise<Todo[]>
}
class TodosView extends LitElement {
private readonly todos = createQueryController(this, {
queryKey: ['todos'],
queryFn: fetchTodos,
})
render() {
const query = this.todos()
// query.data is Todo[] | undefined until success is known.
}
}Checking isSuccess, isPending, isError, or status narrows the result just like TanStack Query Core result types:
const query = this.todos()
if (query.isSuccess) {
query.data
// Todo[]
}import { LitElement } from 'lit'
import { createMutationController } from '@tanstack/lit-query'
type CreateTodoInput = {
title: string
}
type Todo = {
id: number
title: string
}
async function addTodo(input: CreateTodoInput): Promise<Todo> {
const response = await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(input),
})
if (!response.ok) throw new Error('Failed to create todo')
return response.json() as Promise<Todo>
}
class AddTodoButton extends LitElement {
private readonly mutation = createMutationController(this, {
mutationFn: addTodo,
})
private add() {
this.mutation.mutate({ title: 'Learn Lit Query' })
}
}Use queryOptions, infiniteQueryOptions, and mutationOptions when you want to share typed options between controllers and QueryClient calls.
import { LitElement } from 'lit'
import {
QueryClient,
createQueryController,
noop,
queryOptions,
} from '@tanstack/lit-query'
function todosOptions() {
return queryOptions({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 5_000,
})
}
const queryClient = new QueryClient()
class TodosView extends LitElement {
private readonly todos = createQueryController(this, todosOptions())
}
void queryClient.query(todosOptions()).catch(noop)The branded queryKey returned from queryOptions also helps APIs like queryClient.getQueryData understand the data type.
Because @tanstack/lit-query re-exports TanStack Query Core, module augmentation is written against @tanstack/lit-query in Lit apps:
import '@tanstack/lit-query'
type AppQueryKey = ['todos' | 'projects', ...ReadonlyArray<unknown>]
declare module '@tanstack/lit-query' {
interface Register {
queryKey: AppQueryKey
mutationKey: AppQueryKey
}
}See the generated reference for Lit-specific option and result types.