跳转到内容

TypeScript

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

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

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

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

Astro 入门项目在你的项目中包含一个名为 tsconfig.json 的文件。即使你不编写 TypeScript 代码,这个文件也很重要;通过这个文件,可以让 Astro 和 VSCode 等工具知道应当如何理解你的项目。如果没有 tsconfig.json 文件,编辑器将不能对某些功能提供完整支持(比如 npm 包导入)。如果你手动安装的 Astro,请务必自己创建此文件。

Astro 中包含三个可扩展的 tsconfig.json 模板:basestrictstrictestbase 模板开启了对现代 JavaScript 的相关特性的支持,也可用作其他模板的基础。但如果你打算在项目中编写 TypeScript,我们建议使用 strictstrictest。你可以在 astro/tsconfigs/ 中查看和比较这三个配置模板。

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

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

此外,我们的模板在 src 文件夹中包含一个名为 env.d.ts 的文件,它为你的项目提供 Vite 的客户端类型

env.d.ts
/// <reference path="../.astro/types.d.ts" />

TypeScript 编辑器插件

段落标题 TypeScript 编辑器插件

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

该插件仅在编辑器中运行。在终端中运行 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/*"]
}
}
}

扩展 windowglobalThis

段落标题 扩展 window 和 globalThis

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

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

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

注意, window 只能在客户端代码中访问。 globalThis 在服务器端和客户端上都可用,但服务器端值不会共享给客户端。

如果你只想为 window 对象中的一个属性提供类型注释,可以提供一个 Window 接口来实现:

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

Astro 支持通过 TypeScript 来定义你的组件参数。为了启动它,你需要将一个名为 Props 的 TypeScript 接口添加到你的的组件。你可以(可选的)使用 export 语句将其导出,但这不是强制的。Astro VSCode 扩展会自动寻找 Props 接口,并且当你在其他模板内使用该组件时,给你提供适当的 TS 支持。

src/components/HelloProps.astro
---
interface Props {
name: string;
greeting?: string;
}
const { greeting = 'Hello', name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

常见的 Props 类型的套路

段落标题 常见的 Props 类型的套路
  • 如果你的组件没有任何的参数或插槽,你可以使用 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 { 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} />

推断 getStaticPaths() 的类型

段落标题 推断 getStaticPaths() 的类型

添加于: astro@2.1.0

Astro 中有帮助你处理动态路由 getStaticPaths() 函数返回类型的类型。

你可以使用 InferGetStaticParamsTypeInferGetStaticPropsType 来获取 Astro.paramsAstro.props 的类型。

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

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

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

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

段落标题 同时使用多个 JSX 框架所带来的类型错误

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

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

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

// For Preact
/** @jsxImportSource preact */
// For Solid
/** @jsxImportSource solid-js */
贡献

你有什么想法?

社区