TypeScript & Content Types
TypeScript is built in
Section titled “TypeScript is built in”Astro ships TypeScript support out of the box — you can write .ts files, type your component scripts, and get editor type-checking with zero setup. A new project extends one of Astro’s presets in tsconfig.json:
{ "extends": "astro/tsconfigs/strict"}The presets are base, strict, and strictest — pick strict (or strictest) for real projects; it turns on the checks that catch actual bugs.
Typing component props
Section titled “Typing component props”You type a component’s props by declaring a Props interface in the frontmatter. Astro uses it to type-check every place the component is used:
---interface Props { title: string; count?: number; // optional prop}const { title, count = 0 } = Astro.props;---<h1>{title} ({count})</h1>Pass a wrong type or forget a required prop, and the editor (and astro check) flags it at the call site.
Types generated from content schemas
Section titled “Types generated from content schemas”This is where Astro’s typing shines. When you define a content collection with a Zod schema (from the content module), Astro generates TypeScript types from that schema. getCollection and getEntry then return fully-typed entries — your editor knows every frontmatter field and its type:
import { getCollection } from 'astro:content';
const posts = await getCollection('blog');// posts[0].data.title -> string (from the schema)// posts[0].data.pubDate -> Date (z.coerce.date())// posts[0].data.nope -> type error: property does not existflowchart LR schema["Zod schema in src/content.config.ts"] --> gen["Astro generates types"] gen --> query["getCollection / getEntry return typed data"] query --> safe["type errors on wrong field access"]
These types live in a generated .astro/ folder that Astro maintains for you (refreshed by the dev server and by astro sync). You never edit them; you just get autocomplete and safety for free from the schema you already wrote.
Typing Astro.locals
Section titled “Typing Astro.locals”When you use middleware to attach request-scoped data (like the current user) to Astro.locals, you type it by declaring the App.Locals interface, usually in src/env.d.ts:
declare namespace App { interface Locals { user: { id: string; name: string } | null; }}Now Astro.locals.user is typed everywhere — in middleware, pages, and endpoints.
Type-checking with astro check
Section titled “Type-checking with astro check”Editors type-check as you go, but .astro files aren’t checked by tsc. The command that does it is astro check — it validates types across your .astro, .ts, and .tsx files. Wire it into your build so type errors block a broken deploy:
{ "scripts": { "build": "astro check && astro build" }}