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

# TypeScript

> Add type safety to build scripts, component props, content collections, and environment variables.

Aero supports TypeScript in `<script is:build>` blocks, content config files, and shared type modules. The VS Code extension provides IntelliSense and diagnostics automatically. You can type component props, validate content schemas, and run `aero check --types` in CI.

## Ambient types

Aero ships ambient declarations that make `Aero`, `renderComponent`, and `*.html` imports available to TypeScript. Include them in your `tsconfig.json`:

```json tsconfig.json theme={"theme":"github-dark-default"}
{
	"compilerOptions": {
		"types": ["@aero-js/core/env"]
	}
}
```

Or use a triple-slash reference:

```ts theme={"theme":"github-dark-default"}
/// <reference types="@aero-js/core/env" />
```

<Note>
  For `.html` build scripts, the VS Code extension injects these declarations automatically.
  You only need the above for `.ts` files outside of templates.
</Note>

## Typing component props

`Aero.props` is typed as `Record<string, any>` by default. Add type safety with an interface:

```html client/components/greeting.html theme={"theme":"github-dark-default"}
<script is:build>
	interface GreetingProps {
		name: string
		title?: string
	}

	const { name, title = 'Guest' } = Aero.props as GreetingProps
</script>

<h1>Hello, { name }!</h1>
```

For shared types, define them in a `.ts` file and import:

```ts client/types/props.ts theme={"theme":"github-dark-default"}
export interface HeaderProps {
	title: string
	subtitle?: string
}
```

```html client/components/header.html theme={"theme":"github-dark-default"}
<script is:build>
	import type { HeaderProps } from 'types/props'
	const { title, subtitle } = Aero.props as HeaderProps
</script>
```

When you use `as TypeName`, required vs optional comes from the interface (`name` vs `name?`). Without a cast, Aero infers required props from destructuring defaults: no default means required at the call site; a default means optional.

```html theme={"theme":"github-dark-default"}
<script is:build>
	const { title, body = 'No body provided.' } = Aero.props
</script>
```

Here `title` is required and `body` is optional for `aero check` and IDE diagnostics.

## Typing content collections

Use a schema validator in `content.config.ts` to type collection entries:

```ts content.config.ts theme={"theme":"github-dark-default"}
import { defineConfig, defineCollection } from '@aero-js/content'
import { z } from 'zod'

export default defineConfig({
	collections: [
		defineCollection({
			name: 'docs',
			directory: 'client/content/docs',
			schema: z.object({
				title: z.string(),
				published: z.number(),
			}),
		}),
	],
})
```

## Typing import.meta.env

Create an `env.d.ts` to add types for environment variables:

```ts env.d.ts theme={"theme":"github-dark-default"}
/// <reference types="@aero-js/core/env" />

interface ImportMetaEnv {
	readonly SITE: string
	readonly VITE_API_URL: string
}

interface ImportMeta {
	readonly env: ImportMetaEnv
}
```

## CI type-checking

Run type checks in CI without an IDE:

<CodeGroup>
  ```bash pnpm theme={"theme":"github-dark-default"}
  pnpm exec aero check --types
  ```

  ```bash npm theme={"theme":"github-dark-default"}
  npm exec aero check --types
  ```

  ```bash yarn theme={"theme":"github-dark-default"}
  yarn exec aero check --types
  ```
</CodeGroup>

This runs compile checks, then TypeScript on build scripts and `{ }` interpolation sites. See [CLI](/tooling/cli) for flags and exit codes.
