TypeScript
Astro ships with built-in support for TypeScript. You can import .ts
and .tsx
files in your Astro project, write TypeScript code directly inside your Astro component, and even use an astro.config.ts
file if you like.
Using TypeScript, you can prevent errors at runtime by defining the shapes of objects and components in your code. For example, if you use TypeScript to type your component’s props, you’ll get an error in your editor if you set a prop that your component doesn’t accept.
You don’t need to write TypeScript code in your Astro projects to benefit from it. Astro always treats your component code as TypeScript, and the Astro VSCode Extension will infer as much as it can to provide autocompletion, hints, and errors in your editor.
The Astro dev server won’t perform any type checking, but you can use a separate script to check for type errors from the command line.
Setup
Section titled Setup
Astro starter projects include a tsconfig.json
file in your project. Even if you don’t write TypeScript code, this file is important so that tools like Astro and VS Code know how to understand your project. Some features (like npm package imports) aren’t fully supported in the editor without a tsconfig.json
file. If you install Astro manually, be sure to create this file yourself.
TypeScript templates
Section titled TypeScript templates
Three extensible tsconfig.json
templates are included in Astro: base
, strict
, and strictest
. The base
template enables support for modern JavaScript features and is also used as a basis for the other templates. We recommend using strict
or strictest
if you plan to write TypeScript in your project. You can view and compare the three template configurations at astro/tsconfigs/.
To inherit from one of the templates, use the extends
setting:
tsconfig.json
{ "extends": "astro/tsconfigs/base"}
Additionally, our templates include an env.d.ts
file inside the src
folder to provide Vite’s client types to your project:
env.d.ts
/// <reference path="../.astro/types.d.ts" />
TypeScript editor plugin
Section titled TypeScript editor plugin The Astro TypeScript plugin can be installed separately when you are not using the official Astro VS Code extension. This plugin is automatically installed and configured by the VSCode extension, and you do not need to install both.
This plugin runs only in the editor. When running tsc
in the terminal, .astro
files are ignored entirely. Instead, you can use the astro check
CLI command to check both .astro
and .ts
files.
This plugin also supports importing .astro
files from .ts
files (which can be useful for re-exporting).
Terminal window
npm install @astrojs/ts-plugin
Terminal window
pnpm add @astrojs/ts-plugin
Terminal window
yarn add @astrojs/ts-plugin
Then, add the following to your tsconfig.json
:
tsconfig.json
"compilerOptions": { "plugins": [ { "name": "@astrojs/ts-plugin" }, ], }
To check that the plugin is working, create a .ts
file and import an Astro component into it. You should have no warning messages from your editor.
UI Frameworks
Section titled UI Frameworks If your project uses a UI framework, additional settings depending on the framework might be needed. Please see your framework’s TypeScript documentation for more information. (Vue, React, Preact, Solid)
Type Imports
Section titled Type Imports Use explicit type imports and exports whenever possible.
import { SomeType } from './script';import type { SomeType } from './script';
This way, you avoid edge cases where Astro’s bundler may try to incorrectly bundle your imported types as if they were JavaScript.
You can configure TypeScript to enforce type imports in your tsconfig.json
file. Set verbatimModuleSyntax
to true
. TypeScript will check your imports and tell you when import type
should be used. This setting is enabled by default in all our presets.
tsconfig.json
{ "compilerOptions": { "verbatimModuleSyntax": true } }
Import Aliases
Section titled Import Aliases
Astro supports import aliases that you define in your tsconfig.json
paths
configuration. Read our guide to learn more.
src/pages/about/nate.astro
---import HelloWorld from '@components/HelloWorld.astro';import Layout from '@layouts/Layout.astro';---
tsconfig.json
{ "compilerOptions": { "baseUrl": ".", "paths": { "@components/*": ["src/components/*"], "@layouts/*": ["src/layouts/*"] } }}
Extending window
and globalThis
Section titled Extending window and globalThis
You may want to add a property to the global object. You can do this by adding top-level declarations using the declare
keyword to your env.d.ts
file:
env.d.ts
declare var myString: string;declare function myFunction(): boolean;
This will provide typing to globalThis.myString
and globalThis.myFunction
, as well as window.myString
and window.myFunction
.
Note that window
is only available in client-side code. globalThis
is available both server-side and client-side, but its server-side value won’t be shared with the client.
If you only want to type a property on the window
object, provide a Window
interface instead:
env.d.ts
interface Window { myFunction(): boolean;}
Component Props
Section titled Component Props
Astro supports typing your component props via TypeScript. To enable, add a TypeScript Props
interface to your component frontmatter. An export
statement may be used, but is not necessary. The Astro VSCode Extension will automatically look for the Props
interface and give you proper TS support when you use that component inside another template.
src/components/HelloProps.astro
---interface Props { name: string; greeting?: string;}const { greeting = 'Hello', name } = Astro.props;---<h2>{greeting}, {name}!</h2>
Common prop type patterns
Section titled Common prop type patterns
- If your component takes no props or slotted content, you can use
type Props = Record<string, never>
. - If your component must be passed children to its default slot, you can enforce this by using
type Props = { children: any; };
.
Type Utilities
Added in:
astro@1.6.0
Astro comes with some built-in utility types for common prop type patterns. These are available under the astro/types
entrypoint.
Built-in HTML attributes
Section titled Built-in HTML attributes
Astro provides the HTMLAttributes
type to check that your markup is using valid HTML attributes. You can use these types to help build component props.
For example, if you were building a <Link>
component, you could do the following to mirror the default HTML attributes for <a>
tags in your component’s prop types.
src/components/Link.astro
---import type { HTMLAttributes } from 'astro/types';// use a `type`type Props = HTMLAttributes<'a'>;// or extend with an `interface`interface Props extends HTMLAttributes<'a'> { myProp?: boolean;}const { href, ...attrs } = Astro.props;---<a href={href} {...attrs}> <slot /></a>
It is also possible to extend the default JSX definitions to add non-standard attributes by redeclaring the astroHTML.JSX
namespace in a .d.ts
file.
src/custom-attributes.d.ts
declare namespace astroHTML.JSX { interface HTMLAttributes { 'data-count'?: number; 'data-label'?: string; }
// Add a CSS custom property to the style object interface CSSProperties { '--theme-color'?: 'black' | 'white'; }}
Note
astroHTML
is injected globally inside .astro
components. To use it in TypeScript files, use a triple-slash directive:
/// <reference types="astro/astro-jsx" />
type MyAttributes = astroHTML.JSX.ImgHTMLAttributes;
ComponentProps
type
Section titled ComponentProps type
Added in:
astro@4.3.0
This type export allows you to reference the Props
accepted by another component, even if that component doesn’t export that Props
type directly.
The following example shows using the ComponentProps
utility from astro/types
to reference a <Button />
component’s Props
types:
src/pages/index.astro
---import type { ComponentProps } from 'astro/types';
import Button from "./Button.astro";
type ButtonProps = ComponentProps<typeof Button>;---
Polymorphic type
Section titled Polymorphic type
Added in:
astro@2.5.0
Astro includes a helper to make it easier to build components that can render as different HTML elements with full type safety. This is useful for components like <Link>
that can render as either <a>
or <button>
depending on the props passed to it.
The example below implements a fully-typed, polymorphic component that can render as any HTML element. The HTMLTag
type is used to ensure that the as
prop is a valid HTML element.
---import type { HTMLTag, Polymorphic } from 'astro/types';
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }>;
const { as: Tag, ...props } = Astro.props;---
<Tag {...props} />
Infer getStaticPaths()
types
Section titled Infer getStaticPaths() types
Added in:
astro@2.1.0
Astro includes helpers for working with the types returned by your getStaticPaths()
function for dynamic routes.
You can get the type of Astro.params
with InferGetStaticParamsType
and the type of Astro.props
with InferGetStaticPropsType
:
src/pages/posts/[…slug].astro
---import type { InferGetStaticParamsType, InferGetStaticPropsType, GetStaticPaths } from 'astro';
export const getStaticPaths = (async () => { const posts = await getCollection('blog'); return posts.map((post) => { return { params: { slug: post.slug }, props: { draft: post.data.draft, title: post.data.title }, }; });}) satisfies GetStaticPaths;
type Params = InferGetStaticParamsType<typeof getStaticPaths>;type Props = InferGetStaticPropsType<typeof getStaticPaths>;
const { slug } = Astro.params as Params;// ^? { slug: string; }const { title } = Astro.props;// ^? { draft: boolean; title: string; }---
Type checking
Section titled Type checking
To see type errors in your editor, please make sure that you have the Astro VS Code extension installed. Please note that the astro start
and astro build
commands will transpile the code with esbuild, but will not run any type checking. To prevent your code from building if it contains TypeScript errors, change your “build” script in package.json
to the following:
package.json
"scripts": { "build": "astro build", "build": "astro check && astro build", },
Note
astro check
checks all the files included in your TypeScript project. To check types within Svelte and Vue files, you can use the svelte-check
and the vue-tsc
packages respectively.
Read more about .ts
file imports in Astro.
Read more about TypeScript Configuration.
Troubleshooting
Section titled Troubleshooting
Errors typing multiple JSX frameworks at the same time
Section titled Errors typing multiple JSX frameworks at the same time
An issue may arise when using multiple JSX frameworks in the same project, as each framework requires different, sometimes conflicting, settings inside tsconfig.json
.
Solution: Set the jsxImportSource
setting to react
(default), preact
or solid-js
depending on your most-used framework. Then, use a pragma comment inside any conflicting file from a different framework.
For the default setting of jsxImportSource: react
, you would use:
// For Preact/** @jsxImportSource preact */
// For Solid/** @jsxImportSource solid-js */
Learn