# Types: Category to CategoryLookup (/themes/sdk/reference/data/types-1)

```ts
import { … } from '@poltura/theme-sdk/data';
```

## `Category` [#category]

A product category with its place in the category tree.

<TypeTable type={{"id":{"description":"The category's id.","type":"string","required":true},"name":{"description":"The category's name in the page language.","type":"string","required":true},"href":{"description":"The category page's path.","type":"string","required":true},"handle":{"description":"The category's URL segment.","type":"string","required":true},"path":{"description":"The URL segments from the root category down to this one.","type":"readonly string[]","required":true},"parentId":{"description":"The parent category's id, or null for a root category.","type":"string | null","required":true},"description":{"description":"The description, or null.","type":"RichTextValue | null","required":true},"image":{"description":"The category's image, or null.","type":"MediaImageRef | null","required":true},"children":{"description":"The direct subcategories, in the merchant's order.","type":"readonly CategoryRef[]","required":true}}} />

## `CategoryQuery` [#categoryquery]

Which categories [`useCategories`](/themes/sdk/reference/data/hooks-1#usecategories) lists.

<TypeTable type={{"parentId":{"description":"Only the children of this category; null lists the root categories. Omit it for every category.","type":"string | null","required":false},"limit":{"description":"How many categories to list, at most 100. Defaults to 100.","type":"number","required":false}}} />

## `CategoryRef` [#categoryref]

A category as other view models link to it.

<TypeTable type={{"id":{"description":"The category's id.","type":"string","required":true},"name":{"description":"The category's name in the page language.","type":"string","required":true},"href":{"description":"The category page's path.","type":"string","required":true}}} />

## `Collection` [#collection]

A hand-picked group of products with its own page.

<TypeTable type={{"id":{"description":"The collection's id.","type":"string","required":true},"title":{"description":"The collection's title in the page language.","type":"string","required":true},"href":{"description":"The collection page's path.","type":"string","required":true},"handle":{"description":"The collection's URL segment.","type":"string","required":true},"description":{"description":"The description, or null.","type":"RichTextValue | null","required":true},"image":{"description":"The collection's image, or null.","type":"MediaImageRef | null","required":true}}} />

## `CollectionQuery` [#collectionquery]

Which collections [`useCollections`](/themes/sdk/reference/data/hooks-1#usecollections) lists.

<TypeTable type={{"page":{"description":"The page number, from 1. Defaults to 1.","type":"number","required":false},"limit":{"description":"How many items a page holds, at most 100. Defaults to the store's page size.","type":"number","required":false}}} />

## `CollectionRef` [#collectionref]

A collection as other view models link to it.

<TypeTable type={{"id":{"description":"The collection's id.","type":"string","required":true},"title":{"description":"The collection's title in the page language.","type":"string","required":true},"href":{"description":"The collection page's path.","type":"string","required":true}}} />

## `InfiniteQueryResult` [#infinitequeryresult]

What [`useInfiniteProducts`](/themes/sdk/reference/data/hooks-1#useinfiniteproducts) answers: every page loaded so far and a way to load the next.

```ts
type InfiniteQueryResult<T> = Omit<QueryResult<readonly T[]>, 'data'> & {
    readonly pages: readonly T[];
    readonly hasNextPage: boolean;
    readonly isFetchingNextPage: boolean;
    fetchNextPage(): void;
}
```

## `PageRequest` [#pagerequest]

Which page of a list to read.

<TypeTable type={{"page":{"description":"The page number, from 1. Defaults to 1.","type":"number","required":false},"limit":{"description":"How many items a page holds, at most 100. Defaults to the store's page size.","type":"number","required":false}}} />

## `ProductAttribute` [#productattribute]

A merchant-defined product attribute a list can be filtered by, such as material or colour.

<TypeTable type={{"id":{"description":"The attribute's id.","type":"string","required":true},"handle":{"description":"The attribute's stable key, as a filter group id names it.","type":"string","required":true},"name":{"description":"The attribute's name in the page language.","type":"string","required":true},"kind":{"description":"Whether its values are plain choices or colours.","type":"'select' | 'color'","required":true},"unit":{"description":"The unit its values are measured in, such as `cm`, or null.","type":"string | null","required":true},"values":{"description":"The values, in name order.","type":"readonly ProductAttributeValue[]","required":true}}} />

## `ProductAttributeValue` [#productattributevalue]

One value of a product attribute, such as "Cotton" or "Red".

<TypeTable type={{"id":{"description":"The value's id.","type":"string","required":true},"label":{"description":"The value's text in the page language.","type":"string","required":true},"color":{"description":"The colour of a colour attribute's value as a CSS colour, otherwise null.","type":"string | null","required":true},"icon":{"description":"The icon shown beside the value, as `ContentIcon` draws it, or null.","type":"IconValue | null","required":true}}} />

## `ProductPage` [#productpage]

One page of a product list.

<TypeTable type={{"items":{"description":"The products on this page.","type":"readonly ProductCard[]","required":true},"total":{"description":"How many products match over every page.","type":"number","required":true},"page":{"description":"The page number, from 1.","type":"number","required":true},"pageCount":{"description":"How many pages there are.","type":"number","required":true}}} />

## `ProductQuery` [#productquery]

Which products [`useProducts`](/themes/sdk/reference/data/hooks-1#useproducts) lists; every given narrowing applies at once.

<TypeTable type={{"page":{"description":"The page number, from 1. Defaults to 1.","type":"number","required":false},"limit":{"description":"How many items a page holds, at most 100. Defaults to the store's page size.","type":"number","required":false},"search":{"description":"Search words, matched against titles, descriptions and specifications.","type":"string","required":false},"ids":{"description":"Only these products, by id.","type":"readonly string[]","required":false},"handles":{"description":"Only these products, by URL segment.","type":"readonly string[]","required":false},"categoryIds":{"description":"Only products in these categories, by id.","type":"readonly string[]","required":false},"collectionIds":{"description":"Only products in these collections, by id.","type":"readonly string[]","required":false},"tags":{"description":"Only products with these tags, by tag text.","type":"readonly string[]","required":false},"filters":{"description":"A filter selection, as {@link ListingFilterSelection} holds it.","type":"ListingFilterSelection","required":false},"sort":{"description":"The order; defaults to `popularity`.","type":"ProductSort","required":false}}} />

## `ProductSort` [#productsort]

The orders a product list can be sorted in.

```ts
type ProductSort = 'popularity' | 'newest' | 'oldest' | 'titleAsc' | 'titleDesc' | 'priceAsc' | 'priceDesc'
```

## `ProductTypeRef` [#producttyperef]

A product type, such as "T-shirt" or "Gift card".

<TypeTable type={{"id":{"description":"The type's id.","type":"string","required":true},"name":{"description":"The type's name in the page language.","type":"string","required":true}}} />

## `QueryOptions` [#queryoptions]

Options every data hook takes.

<TypeTable type={{"enabled":{"description":"Whether the read runs; false keeps it idle until the inputs it needs are known. Defaults to true.","type":"boolean","required":false},"suspense":{"description":"Suspends the component until the answer arrives, so `data` is never undefined.","type":"boolean","required":false},"keepPrevious":{"description":"Keeps showing the previous answer while new inputs load, such as the next page.","type":"boolean","required":false}}} />

## `QueryResult` [#queryresult]

What a data hook answers: the data once it arrived, the read's status and a way to read again.

```ts
type QueryResult<T>
```

<TypeTable type={{"data":{"description":"The answer, or undefined while the first one loads or after a failure.","type":"T | undefined","required":true},"status":{"description":"Where the read is.","type":"QueryStatus","required":true},"error":{"description":"Why the read failed, or null.","type":"StoreReadError | null","required":true},"isFetching":{"description":"Whether a read is in flight, the first one or a refresh.","type":"boolean","required":true},"refetch":{"description":"Reads again.","type":"() => void","required":true}}} />

## `QueryStatus` [#querystatus]

Where a read is: still loading its first answer, failed, or answered.

```ts
type QueryStatus = 'pending' | 'error' | 'success'
```

## `StoreReadErrorCode` [#storereaderrorcode]

Why a store read failed.

```ts
type StoreReadErrorCode = 'forbidden' | 'unknownKind' | 'badParams' | 'unauthenticated' | 'budget' | 'tooLarge' | 'timeout' | 'unavailable' | 'internal'
```

## `SuspenseQueryOptions` [#suspensequeryoptions]

[`QueryOptions`](/themes/sdk/reference/data/types-1#queryoptions) that suspend: the hook answers a [`SuspenseQueryResult`](/themes/sdk/reference/data/types-1#suspensequeryresult).

```ts
type SuspenseQueryOptions = Omit<QueryOptions, 'suspense' | 'enabled'> & {
    readonly suspense: true;
}
```

## `SuspenseQueryResult` [#suspensequeryresult]

What a data hook answers with `{ suspense: true }`: the component renders only once the data is there.

```ts
type SuspenseQueryResult<T> = Omit<QueryResult<T>, 'data' | 'status' | 'error'> & {
    readonly data: T;
    readonly status: 'success';
    readonly error: null;
}
```

## `ProductLookup` [#productlookup]

Names one product, by its URL segment or by its id.

```ts
type ProductLookup = {
    readonly handle: string;
} | {
    readonly id: string;
}
```

## `CategoryLookup` [#categorylookup]

Names one category, by its URL path from the root or by its id.

```ts
type CategoryLookup = {
    readonly path: readonly string[];
} | {
    readonly id: string;
}
```
