TypeScript 支持
本教程共 56 篇 · 第 43 篇 · 更新于 2026-08-07 · 约 10 分钟阅读
本节目标:了解 Astro 内建的 TypeScript 支持,tsconfig 模板、
astro check类型检查、组件 Props 类型与工具类型分别怎么用。
Astro 内建支持 TypeScript(微软推出的 JavaScript 超集,给代码加类型标注)。好处是:你提前标注”这个对象长什么样、这个组件能收哪些属性”,编辑器就能在写错时立刻提醒,把很多运行时错误挡在写代码阶段。本章讲 Astro 里 TypeScript 的常用姿势。
不用写 TS 也能受益
先放宽心:你不写 TypeScript,也照样能享受它的好处。Astro 始终把你的组件脚本当成 TypeScript 来处理;装上官方的 Astro VS Code 扩展后,它会尽可能推断类型,给你自动补全、提示和报错。所以哪怕全程写普通 JavaScript,体验也会比裸写强。
不过开发服务器不会做类型检查(它用 esbuild 只转译)。要命令行查类型,得用 astro check(第 42 章)。
tsconfig 模板
每个 Astro 起步项目都带一个 tsconfig.json。即使你不写 TS,这个文件也很重要——它让 VS Code、Astro 理解你的项目(比如有些 npm 包导入没它就不识别)。Astro 内置三套可继承的模板:
base:支持现代 JavaScript 特性,也是另两套的基础。strict:更严格的类型检查。strictest:最严格。
打算写 TS,推荐从 strict 或 strictest 起步。继承方式用 extends:
{
"extends": "astro/tsconfigs/base"
}
建议再加上 include 和 exclude,既能用到 Astro 类型、又跳过构建产物:
{
"extends": "astro/tsconfigs/base",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}
TypeScript 编辑器插件
如果你没用官方 VS Code 扩展,可以单独装 @astrojs/ts-plugin,让编辑器支持 .astro 文件的类型。VS Code 扩展已经自动配好它,两者不用都装。这个插件只在编辑器里跑;在终端跑 tsc 时会忽略 .astro 文件——此时用 astro check 来检查 .astro 和 .ts。
UI 框架的额外设置
项目里用了 React / Vue / Svelte 等框架组件时,可能要在 tsconfig.json 里加对应框架的 TypeScript 设置。具体看各框架自己的文档。
显式类型导入
尽量用 import type 显式导入类型:
import type { SomeType } from "./script";
这样能避免打包器误把”类型”当”代码”打包。可以在 tsconfig.json 里设 verbatimModuleSyntax: true(Astro 预设默认开启),让 TypeScript 强制你用 import type。
导入别名
在 tsconfig.json 的 paths 里配导入别名(import alias,给长路径起个短名字),写 import 就更清爽:
{
"compilerOptions": {
"paths": {
"@components/*": ["./src/components/*"],
"@layouts/*": ["./src/layouts/*"]
}
}
}
之后就能写 import HelloWorld from "@components/HelloWorld.astro",不用数 ../。
扩展全局类型
约定上用 src/env.d.ts 放自定义类型声明,或补充 Astro 类型。例如给全局对象加属性:
// src/env.d.ts
declare var myString: string;
interface Window {
myFunction(): boolean;
}
想给自定义 HTML 属性或 CSS 变量加类型,可重声明 astroHTML.JSX 命名空间:
declare namespace astroHTML.JSX {
interface HTMLAttributes {
"data-count"?: number;
}
interface CSSProperties {
"--theme-color"?: "black" | "white";
}
}
Note
.d.ts是环境声明文件,语法像模块但不能有顶层 import/export,否则会变成”模块增强”而破坏全局类型。
组件 Props 类型
给组件属性加类型,是 TS 在 Astro 里最常见的用法。在组件 frontmatter 里写个 Props 接口即可:
---
// src/components/HelloProps.astro
interface Props {
name: string;
greeting?: string;
}
const { greeting = "Hello", name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
VS Code 扩展会自动找这个 Props 接口,你在该组件被使用时就有类型提示。两个常见模式:无属性用 type Props = Record<string, never>;必须有插槽内容用 type Props = { children: any }。
内置工具类型
Astro 在 astro/types 下提供几个顺手的类型工具:
- HTMLAttributes:检查你用的 HTML 属性是否合法。比如做
<Link>组件时复用<a>的属性类型:
---
import type { HTMLAttributes } from "astro/types";
type Props = HTMLAttributes<"a">;
const { href, ...attrs } = Astro.props;
---
<a href={href} {...attrs}><slot /></a>
- ComponentProps(v4.3+):引用别的组件收的
Props类型,哪怕它没导出:
import type { ComponentProps } from "astro/types";
import Button from "./Button.astro";
type ButtonProps = ComponentProps<typeof Button>;
-
Polymorphic(v2.5+):做一个能渲染成不同 HTML 标签、还带完整类型的组件(如既能是
<a>又能是<button>的<Link>)。 -
推断 getStaticPaths 类型:
InferGetStaticParamsType、InferGetStaticPropsType、GetStaticPath(动态路由第 15 章用得上),帮你拿到Astro.params和Astro.props的精确类型。
类型检查怎么接进构建
想让”有类型错误就构建失败”,把 build 脚本改成先 check 再 build:
{
"scripts": {
"build": "astro check && astro build"
}
}
多个 JSX 框架冲突
同一项目用多个 JSX 框架(React + Preact + Solid)时,tsconfig.json 的 JSX 设置会打架。解法:把 jsxImportSource 设成你最常用的那个(默认 react),在”不同框架”的文件顶部加 pragma 注释:
// 给 Preact 文件加:
/** @jsxImportSource preact */
// 给 Solid 文件加:
/** @jsxImportSource solid-js */
strict 与 strictest 差在哪
base 只开现代 JS 特性;strict 开启 TypeScript 的标准严格检查;strictest 在 strict 基础上再加更严的规则(比如禁止隐式 any、要求显式返回值等)。新手从 strict 起步压力适中;团队项目追求质量可用 strictest。
类型从哪来:astro/client
Astro 自动生成 .astro/types.d.ts,里面有 astro:* 系列虚拟模块的类型、内容集合类型等。它就是 astro sync 的产物,也是编辑器能识别 astro:content、astro:actions 的原因。一般你不用手动碰它,知道”类型自动生成”即可。
一个 Props 类型的实用例子
除了基础属性,配合 HTMLAttributes 复用原生标签类型很常见。比如做卡片组件:
---
import type { HTMLAttributes } from "astro/types";
type Props = HTMLAttributes<"div"> & { variant?: "default" | "highlight" };
const { variant = "default", ...attrs } = Astro.props;
---
<div class={variant} {...attrs}><slot /></div>
这样卡片既能收自定义 variant,又能收普通 <div> 的所有属性(如 id、class、style)。
astro check 和 tsc 的区别
终端里跑 tsc 会忽略 .astro 文件(它不认识这种格式);而 astro check 专门能查 .astro 和 .ts。所以检查 Astro 项目请用 astro check,别用裸 tsc。编辑器里的报错则来自 TS 插件(或 VS Code 扩展),和 astro check 是两套互补的检查,一个写代码时提示、一个命令行里把关。
类型报错怎么读
类型报错看起来吓人,但套路固定:先看”哪个文件哪一行”,再看”期望的类型”和”你给的类型”哪里不一致。比如 Props 标了 name: string,你用组件时没传 name,就会报”缺少属性 name”。从具体属性名入手,比通读整段报错高效。
让 .astro 文件被 TS 识别
.astro 不是标准文件类型,要让 tsc、打包器和编辑器正确识别它,靠的就是 astro sync 生成的 .astro/types.d.ts(里面声明了 *.astro 模块)。所以如果你在 .ts 文件里 import 一个 .astro 组件却报”找不到模块”,先跑一次 astro sync(或 astro dev 会自动跑)。这也是为什么前面说”sync 产物是类型基础”。
给全局状态加类型:App.Locals
中间件(第 37 章)里常往 context.locals 塞用户信息等数据,方便后续页面读取。你可以在 env.d.ts 里给 App.Locals 加类型,这样读写 locals 都有提示:
declare namespace App {
interface Locals {
user: import("my-lib").User | null;
}
}
这种”扩展全局类型”的方式,让你在不改 Astro 源码的前提下,把自定义数据接进框架的类型系统。类似的还有给 astro:env、内容集合加类型,思路一致:都在 env.d.ts 或 astro/types 上做声明合并。
小结
Astro 内建 TypeScript:组件脚本就是 TS,装 VS Code 扩展即可享受推断。类型检查靠 astro check,可接进 build 脚本。tsconfig.json 用 astro/tsconfigs 模板继承;组件 Props 用 Props 接口标注;astro/types 下还有 HTMLAttributes、ComponentProps 等工具类型。多 JSX 框架冲突用 jsxImportSource + pragma 解决。
下一章我们看开发工具栏:写代码时有哪些现成的调试帮手。