跳转到内容

TypeScript

Astro 内置了对 TypeScript 的支持。你可以在 Astro 项目中导入 .ts.tsx 文件,在 Astro 组件中直接编写 TypeScript 代码,甚至可以使用 astro.config.ts 文件来配置 Astro。

使用 TypeScript,你可以通过在代码中定义对象和组件的形态来防止运行时错误。例如,如果你使用 TypeScript 为组件的 props 添加类型,当你设置一个组件不接受的 prop 时,你的编辑器就会报错。

你无需在 Astro 项目中编写 TypeScript 代码也能从中受益。Astro 始终将你的组件代码视为 TypeScript,并且 Astro VS Code 扩展会尽可能地推断类型,以便在你的编辑器中提供自动补全、提示和错误。

Astro 开发服务器不会执行任何类型检查,但你可以使用单独的脚本从命令行检查类型错误。

Astro 入门项目在你的项目中包含一个 tsconfig.json 文件。即使你不编写 TypeScript 代码,这个文件也很重要,这样像 Astro 和 VS Code 这样的工具才能知道如何理解你的项目。如果没有 tsconfig.json 文件,某些功能(如 npm 包导入)在编辑器中将无法得到完全支持。如果你是手动安装 Astro,请务必自己创建此文件。

Astro 中包含了三个可扩展的 tsconfig.json 模板:basestrictstrictestbase 模板启用了对现代 JavaScript 功能的支持,并作为其他模板的基础。如果你计划在项目中使用 TypeScript,我们建议使用 strictstrictest。你可以在 astro/tsconfigs/ 查看和比较这三个模板的配置。

要继承其中一个模板,请使用 extends 设置

tsconfig.json
{
"extends": "astro/tsconfigs/base"
}

此外,我们建议按如下方式设置 includeexclude,以利用 Astro 类型并避免检查已构建的文件

tsconfig.json
{
"extends": "astro/tsconfigs/base",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}

你可以创建一个 src/env.d.ts 文件,这是一种约定俗成的做法,用于添加自定义类型声明,或者在没有 tsconfig.json 文件的情况下利用 Astro 的类型。

src/env.d.ts
// Custom types declarations
declare var myString: string;
// Astro types, not necessary if you already have a `tsconfig.json`
/// <reference path="../.astro/types.d.ts" />

如果你没有使用官方的 Astro VS Code 扩展,可以单独安装 Astro TypeScript 插件。该插件由 VS Code 扩展自动安装和配置,你无需同时安装两者。

此插件仅在编辑器中运行。在终端中运行 tsc 时,.astro 文件会被完全忽略。你可以改用 astro check CLI 命令来检查 .astro.ts 文件。

此插件还支持从 .ts 文件导入 .astro 文件(这对于重新导出很有用)。

终端窗口
npm install @astrojs/ts-plugin

然后,将以下内容添加到你的 tsconfig.json

tsconfig.json
{
"compilerOptions": {
"plugins": [
{
"name": "@astrojs/ts-plugin"
},
],
}
}

要检查插件是否正常工作,请创建一个 .ts 文件并在其中导入一个 Astro 组件。你的编辑器中不应该出现任何警告信息。

如果你的项目使用了 UI 框架,可能需要根据所用框架进行额外设置。请参阅你的框架的 TypeScript 文档以获取更多信息。(Vue, React, Preact, Solid

尽可能使用显式类型导入和导出。

import { SomeType } from "./script";
import type { SomeType } from "./script";

这样,你就可以避免 Astro 的打包器可能错误地将导入的类型当作 JavaScript 来打包的边缘情况。

你可以在 tsconfig.json 文件中配置 TypeScript 以强制使用类型导入。将 verbatimModuleSyntax 设置为 true。TypeScript 将检查你的导入,并在应该使用 import type 时通知你。此设置在我们的所有预设中默认启用。

tsconfig.json
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}

Astro 支持你在 tsconfig.jsonpaths 配置中定义的导入别名阅读我们的指南以了解更多信息。

src/pages/about/nate.astro
---
import HelloWorld from "@components/HelloWorld.astro";
import Layout from "@layouts/Layout.astro";
---
tsconfig.json
{
"compilerOptions": {
"paths": {
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"]
}
}
}

你可能想要向全局对象添加一个属性。你可以通过在你的 env.d.ts 文件中使用 declare 关键字添加顶级声明来实现

src/env.d.ts
declare var myString: string;
declare function myFunction(): boolean;

这将为 globalThis.myStringglobalThis.myFunction 以及 window.myStringwindow.myFunction 提供类型。

请注意,window 仅在客户端代码中可用。globalThis 在服务器端和客户端都可用,但其服务器端的值不会与客户端共享。

如果你只想为 window 对象上的属性提供类型,可以改为提供一个 Window 接口

src/env.d.ts
interface Window {
myFunction(): boolean;
}

Astro 支持通过 TypeScript 为组件的 props 添加类型。要启用此功能,请在组件的 frontmatter 中添加一个 TypeScript Props 接口。可以使用 export 语句,但不是必需的。当你在另一个模板中使用该组件时,Astro VS Code 扩展将自动查找 Props 接口,并为你提供正确的 TS 支持。

src/components/HelloProps.astro
---
interface Props {
name: string;
greeting?: string;
}
const { greeting = "Hello", name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
  • 如果你的组件不接受任何 props 或插槽内容,你可以使用 type Props = Record<string, never>
  • 如果你的组件必须将子元素传递给其默认插槽,你可以通过使用 type Props = { children: any; }; 来强制执行此操作。

添加于: astro@1.6.0

Astro 自带了一些用于常见 prop 类型模式的内置工具类型。这些类型可以在 astro/types 入口下找到。

Astro 提供了 HTMLAttributes 类型来检查你的标记是否使用了有效的 HTML 属性。你可以使用这些类型来帮助构建组件 props。

例如,如果你正在构建一个 <Link> 组件,你可以执行以下操作,以在组件的 prop 类型中镜像 <a> 标签的默认 HTML 属性。

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>

也可以通过在 .d.ts 文件中重新声明 astroHTML.JSX 命名空间来扩展默认的 JSX 定义,以添加非标准属性。

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";
}
}

添加于: astro@4.3.0

即使另一个组件没有直接导出其 Props 类型,此类型导出也允许你引用该组件接受的 Props

下面的示例展示了如何使用来自 astro/typesComponentProps 工具来引用 <Button /> 组件的 Props 类型

src/pages/index.astro
---
import type { ComponentProps } from "astro/types";
import Button from "./Button.astro";
type ButtonProps = ComponentProps<typeof Button>;
---

添加于: astro@2.5.0

Astro 包含一个辅助函数,可以更轻松地构建能够以不同 HTML 元素呈现并具有完全类型安全的组件。这对于像 <Link> 这样的组件很有用,它可以根据传递给它的 props 渲染为 <a><button>

下面的示例实现了一个完全类型化的多态组件,可以渲染为任何 HTML 元素。HTMLTag 类型用于确保 as prop 是一个有效的 HTML 元素。

---
import type { HTMLTag, Polymorphic } from "astro/types";
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }>;
const { as: Tag, ...props } = Astro.props;
---
<Tag {...props} />

添加于: astro@2.1.0

Astro 包含一些辅助函数,用于处理动态路由的 getStaticPaths() 函数返回的类型。

你可以使用 InferGetStaticParamsType 获取 Astro.params 的类型,使用 InferGetStaticPropsType 获取 Astro.props 的类型,或者你可以使用 GetStaticPaths 来一次性推断两者

src/pages/posts/[...id].astro
---
import type {
InferGetStaticParamsType,
InferGetStaticPropsType,
GetStaticPaths,
} from "astro";
export const getStaticPaths = (async () => {
const posts = await getCollection("blog");
return posts.map((post) => {
return {
params: { id: post.id },
props: { draft: post.data.draft, title: post.data.title },
};
});
}) satisfies GetStaticPaths;
type Params = InferGetStaticParamsType<typeof getStaticPaths>;
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
const { id } = Astro.params as Params;
// ^? { id: string; }
const { title } = Astro.props;
// ^? { draft: boolean; title: string; }
---

要在编辑器中查看类型错误,请确保你已安装 Astro VS Code 扩展。请注意,astro startastro build 命令会使用 esbuild 转译代码,但不会运行任何类型检查。为了防止在代码包含 TypeScript 错误时进行构建,请将 package.json 中的“build”脚本更改为以下内容

package.json
{
"scripts": {
"build": "astro build",
"build": "astro check && astro build",
},
}
在 Astro 中阅读有关 .ts 文件导入 的更多信息。
阅读有关 TypeScript 配置 的更多信息。

在同一项目中使用多个 JSX 框架时可能会出现问题,因为每个框架在 tsconfig.json 中需要不同且有时会相互冲突的设置。

解决方案:根据你最常使用的框架,将 jsxImportSource 设置react(默认)、preactsolid-js。然后,在来自不同框架的任何冲突文件中使用编译指示注释

对于 jsxImportSource: react 的默认设置,你可以使用

// For Preact
/** @jsxImportSource preact */
// For Solid
/** @jsxImportSource solid-js */
贡献 社区 赞助