跳转到内容

TypeScript

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

使用 TypeScript,你可以通过约束代码中对象和组件的类型来防止运行时的错误。例如,如果你使用了 TypeScript 来定义组件参数;而如果你在使用时不小心传入了一个与之不匹配的参数,编辑器将会报错。

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

Astro 的开发服务器不会进行任何类型检查,但你可以编辑 package.json 中的 scripts 属性来通过命令行工具检查代码中的类型错误。

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
// 自定义类型声明
declare var myString: string;
// Astro 类型,如果你已经有 `tsconfig.json`,则不需要
/// <reference path="../.astro/types.d.ts" />

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

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

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

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

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

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

要检查插件是否正常工作,创建一个 .ts 文件,并在里面导入一个 Astro 组件。你的编辑器应该没有警告消息。

如果你的项目使用了 UI 框架,则可能需要根据框架的不同进行额外的设置。请参阅你使用的框架的文档中关于 TypeScript 的相关文档以获取更多信息。(VueReactPreactSolid

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

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

通过这种方式,你可以避免让 Astro 的打包程序将导入的类型误以为是 JavaScript,从而错误地被打包。

你可以在 tsconfig.json 文件配置 TypeScript 强制执行类型导入。设置 verbatimModuleSyntaxtrue。TypeScript 会检查你的导入并告诉你什么时候应该使用 import type。这个设置在我们所有的预设里都是默认启用的。

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

Astro 支持你在 tsconfig.json 文件里的 paths 配置所定义的 导入别名

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/*"]
}
}
}

你可能需要在全局对象中添加一项属性。可以通过在 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 的 TypeScript 接口添加到你的的组件。你可以(可选的)使用 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>
  • 如果你的组件没有任何的参数或插槽,你可以使用 type Props = Record<string, never>
  • 如果你的组件必须将一个子组件传递给默认插槽,你可以使用 type Props = { children: any; };

添加于: astro@1.6.0

Astro 为常见的组件参数的类型模式准备了一些实用的类型工具集。这些可以通过在代码中引入 astro/types 来使用。

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

例如,如果你正在构建一个 <Link> 组件,你可以通过以下语法来为组件的 Props 类型镜像 <a> 的默认的 HTML 属性。

src/components/Link.astro
---
import type { HTMLAttributes } from "astro/types";
// 使用 `type`
type Props = HTMLAttributes<"a">;
// 或者通过 `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;
}
// 添加一个 CSS 自定义属性到 style 对象中
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 属性是一个有效的 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() 函数返回类型的类型。

你可以使用 InferGetStaticParamsTypeInferGetStaticPropsType 来获取 Astro.paramsAstro.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 框架所带来的类型错误

Section titled “同时使用多个 JSX 框架所带来的类型错误”

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

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

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

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