Skip to content

Latest commit

 

History

History
326 lines (232 loc) · 15.7 KB

typescript.mdx

File metadata and controls

326 lines (232 loc) · 15.7 KB
title description i18nReady
TypeScript
Astro組み込みのTypeScriptサポートの使い方を学ぶ。
true

import Since from '/components/Since.astro' import PackageManagerTabs from '/components/tabs/PackageManagerTabs.astro'

AstroにはTypeScriptのサポートが組み込まれています。Astroプロジェクトで.ts.tsxファイルをインポートしたり、Astroコンポーネントの中で直接TypeScriptコードを書いたり、お好みでastro.config.tsファイルを使うこともできます。

TypeScriptにより、オブジェクトやコンポーネントの形状(shape)をコードで定義して実行時エラーを防ぐことができます。たとえば、TypeScriptでコンポーネントのpropsに型を付けると、コンポーネントが受け付けないpropを設定した場合にエディタ内にエラーが発生します。

AstroプロジェクトでTypeScriptコードを書かなくても、その恩恵を受けられます。Astroは常にコンポーネントのコードをTypeScriptとして扱い、Astro VSCode拡張機能は自動補完やヒント、エラーをエディタ内で提供するためにできる限りの推論を行います。

Astroの開発サーバーは型チェックを行いませんが、スクリプトの追加によりコマンドラインから型エラーをチェックできます。

準備

Astroのスタータープロジェクトにはtsconfig.jsonファイルが含まれています。TypeScriptコードを書かない場合でも、AstroやVS Codeなどのツールがプロジェクトを理解するために、このファイルは重要です。tsconfig.jsonファイルがないと、npmパッケージのインポートなどの一部の機能がエディタで完全にサポートされません。Astroを手動でインストールする場合は、必ずこのファイルを自分で作成してください。

Astroには、basestrictstrictestという3つの拡張可能なtsconfig.jsonのテンプレートが含まれています。baseテンプレートは、JavaScriptのモダンな機能のサポートを可能とし、他のテンプレートの基礎としても使用されます。プロジェクトでTypeScriptを書く予定がある場合は、strictまたはstrictestを使用することをお勧めします。astro/tsconfigs/で3つのテンプレートの設定を確認・比較できます。

いずれかのテンプレートを継承するには、extendsという設定項目を使用します。

{
  "extends": "astro/tsconfigs/base"
}

また、Viteのクライアント型をプロジェクトで利用できるように、テンプレートにはsrcフォルダ内にenv.d.tsが含まれています。

/// <reference types="astro/client" />

VSCodeを使っていない場合は、Astro TypeScriptプラグインをインストールすることで、.tsファイルからの.astroファイルのインポートをサポートできます(これは再エクスポートに便利なことがあります)。

```shell npm install @astrojs/ts-plugin ``` ```shell pnpm add @astrojs/ts-plugin ``` ```shell yarn add @astrojs/ts-plugin ```

そして、以下の設定をtsconfig.jsonに追加します。

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

プラグインが正しく機能していることを確認するには、.tsファイルを作成し、その中にAstroコンポーネントをインポートします。エディタには警告メッセージが何も表示されないはずです。

UIフレームワーク

プロジェクトでUIフレームワークを使用する場合は、フレームワークに応じた追加の設定が必要かもしれません。詳細については、フレームワークのTypeScriptドキュメントを参照してください。 (VueReactPreactSolid)

型のインポート

可能な限り、明示的な型のインポートとエクスポートを使用しましょう。

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

こうすることで、Astroのバンドラーがインポートした型をJavaScriptであるかのように誤ってバンドルするようなエッジケースを避けることができます。

tsconfig.jsonファイルで、型のインポートを強制するようにTypeScriptを設定できます。verbatimModuleSyntaxtrueに設定してください。TypeScriptはインポートをチェックし、いつimport typeを使用するべきかを伝えてくれます。この設定はAstroのすべてのプリセットでデフォルトで有効化されています。

  {
    "compilerOptions": {
      "verbatimModuleSyntax": true
    }
  }

Importエイリアス

Astroは、tsconfig.jsonjsconfig.jsonpaths設定で定義するimportエイリアスをサポートしています。

---
import HelloWorld from '@components/HelloWorld.astro';
import Layout from '@layouts/Layout.astro';
---
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@layouts/*": ["src/layouts/*"]
    }
  }
}

windowglobalThisの拡張

グローバルオブジェクトにプロパティを追加することもできます。これは、env.d.tsファイルにdeclareキーワードを使用してトップレベルの宣言を追加することで可能です。

declare const myString: string;
declare function myFunction(): boolean;

これにより、globalThis.myStringglobalThis.myFunction、さらにwindow.myStringwindow.myFunctionに型が提供されます。

windowはクライアントサイドのコード内でのみ利用可能なことに注意してください。globalThisはサーバーサイドとクライアントサイドの両方で利用できますが、サーバーサイドの値はクライアントとは共有されません。

windowオブジェクト上のプロパティにのみ型付けしたい場合は、代わりにWindowインターフェイスを提供してください。

interface Window {
	myFunction(): boolean;
}

コンポーネントProps

AstroはTypeScriptによるコンポーネントpropsの型付けをサポートしています。有効にするには、コンポーネントのfrontmatterにTypeScriptのPropsインターフェースを追加します。export文を使用することもできますが、必須ではありません。Astro VSCode拡張機能は、Propsインターフェースを自動的に探し、そのコンポーネントを他のテンプレート内で使用するときに適切なTSサポートを提供します。

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

propsの型でよくあるパターン

  • コンポーネントがpropsやスロット経由のコンテンツを受け取らない場合は、type Props = Record<string, unknown>を使用できます。

  • コンポーネントがデフォルトスロットから子要素を受け取る必要がある場合は、type Props = { children: any; };によりこれを強制できます。

型ユーティリティ

Astroには、propsに型を付ける際によく出くわすパターン向けに、組み込みのユーティリティ型を提供しています。これらはastro/typesエントリポイントから利用可能です。

組み込みのHTML属性

Astroは、マークアップが有効なHTML属性を使用していることを確認するためにHTMLAttributes型を提供しています。この型により、コンポーネントのpropsを構成しやすくなります。

たとえば<Link>コンポーネントを作成する場合、次のようにコンポーネントのprops型に<a>タグのデフォルトHTML属性を反映できます。

---
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のカスタムプロパティをスタイルオブジェクトに追加する
  interface CSSProperties {
    '--theme-color'?: 'black' | 'white';
  }
}

:::note astroHTML.astroコンポーネント内にグローバルに注入されます。TypeScriptファイルで使用するには、triple-slashディレクティブを使用します。

/// <reference types="astro/astro-jsx" />

type MyAttributes = astroHTML.JSX.ImgHTMLAttributes;

:::

ComponentProps

この型エクスポートを利用すると、別のコンポーネントがProps型を直接エクスポートしていなかったとしても、そのコンポーネントが受け付けるPropsを参照できるようになります。

以下に示すのは、astro/typesComponentPropsを使用して<Button />コンポーネントのProps型を参照する例です。

---
import type { ComponentProps } from 'astro/types';

import Button from "./Button.astro";

type ButtonProps = ComponentProps<typeof Button>;
---

ポリモーフィックな型

Astroには、異なるHTML要素としてレンダリング可能なコンポーネントを、完全に型安全に作成することを簡単にするヘルパーがあります。これは、渡されたpropsに応じて、<a>または<button>のいずれかとしてレンダリングされる<Link>のようなコンポーネントに便利です。

以下の例では、完全に型付けされた、任意の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} />

getStaticPaths()の型の推論

Astroには、動的ルーティングに対してgetStaticPaths()関数から返される型を扱うためのヘルパーがあります。

Astro.paramsの型はInferGetStaticParamsTypeで、Astro.propsの型はInferGetStaticPropsTypeで取得できます。

---
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 VS Code拡張機能をインストールしてください。astro startastro buildコマンドは、esbuildでコードをトランスパイルしますが、型チェックは実行しないことに注意してください。TypeScriptのエラーが含まれている場合にビルドされないようにするには、package.jsonのbuildスクリプトを次のように変更します。

  "scripts": {
    "build": "astro build",
    "build": "astro check && astro build",
  },

:::note astro checkは、TypeScriptプロジェクトに含まれるすべてのファイルをチェックします。SvelteとVueファイル内の型をチェックするには、それぞれsvelte-checkvue-tscパッケージを使用できます。 :::

import ReadMore from '~/components/ReadMore.astro'

Astroにおける.tsファイルのインポートについてもっと読む。

TypeScriptの設定についてもっと読む。

トラブルシューティング

同時に複数のJSXフレームワークを型付けしたときのエラー

同じプロジェクトで複数のJSXフレームワークを使用する場合、フレームワークごとにtsconfig.json内の設定が異なり、互いにコンフリクトして問題が発生することがあります。

解決策:最も使用するフレームワークに合わせて、jsxImportSource設定react(デフォルト)、preactまたはsolid-jsに設定します。次に、競合する異なるフレームワークのファイル内でプラグマコメントを使用します。

デフォルト設定であるjsxImportSource: reactの場合は、次のように使用します。

// Preact向け
/** @jsxImportSource preact */

// Solid向け
/** @jsxImportSource solid-js */