> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nexudus.com/llms.txt
> Use this file to discover all available pages before exploring further.

# createShape

> Type-safe field selection for server-side shaping with compile-time validation.

# createShape

`createShape<T>()` builds a compile-time checked list of fields to request from the server. It validates dot-paths against `T` and produces a phantom `type` that represents the shaped response. Pair it with `useData` or `useTypedData` to append `_shape=...` to requests.

Source: `src/helpers/shape-helper.ts`

## Why

* Keep responses small by requesting only what you need
* Maintain end-to-end type safety: invalid paths fail at compile time
* Works with nested objects and arrays (e.g. `Records.Items.Name` or `Posts.Title`)

## Usage

```ts theme={null}
const shape = createShape<ResponseType>()(['Records.Id', 'Records.Name'])

// shape.fields → ['Records.Id', 'Records.Name']
// shape.type   → { Records: { Id: number; Name: string }[] } (phantom type)
```

Then pass `shape.fields` through `useData` or directly pass the shape object to `useTypedData`:

```tsx theme={null}
const { resource } = useTypedData(httpClient, endpoint, shape)
```

## Arrays and nesting

If `Posts` is an array, `'Posts.Title'` yields `{ Posts: { Title: string }[] }` in `shape.type`.

## Compile-time validation

Invalid paths produce a TypeScript error via `ValidatePaths<T, Paths>`.

```ts theme={null}
// Error: Invalid path: "profiles.fullName" if fullName doesn’t exist
const shape = createShape<User>()(['id', 'profiles.fullName'])
```

## End-to-end example

```tsx theme={null}
import endpoints from '@/api/endpoints'
import { useTypedData } from '@/api/fetchData'
import { createShape } from '@/helpers/shape-helper'

const endpoint = endpoints.teams.list(true)
const shape = createShape<typeof endpoint.type>()(['Records.Id', 'Records.Name'])
const { resource } = useTypedData(httpClient, endpoint, shape)
```

## Best practices

* Define shapes next to the data hook or at top-level when reused across components
* Name exported shapes descriptively, e.g. `teamListShape`
* Keep shapes minimal; add fields only when needed by the UI

## See also

* [useData](/developers/data/use-data)
* [useTypedData](/developers/data/use-typed-data)
