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.

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.

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 types="astro/client" />

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)

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.

In your .tsconfig file, you can instruct TypeScript to help with this. The importsNotUsedAsValues setting can be set to error. Then, TypeScript will check your imports and tell you when import type should be used. This setting is included by default in our strict and strictest templates.

tsconfig.json
{
  "compilerOptions": {
    "importsNotUsedAsValues": "error",
  }
}

Astro supports import aliases that you define in your tsconfig.json & jsconfig.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/*"]
    }
  }
}

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>
  • 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; };.

Added in: v1.6.0

Astro comes with some built-in utility types for common prop type patterns. These are available under the astro/types entrypoint.

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} {...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;
  }
}

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 && tsc --noEmit && astro build",
  },

📚 Read more about .ts file imports in Astro. 📚 Read more about TypeScript Configuration.

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 */