Svelte コンポーネント内で TypeScript を使えます。[Svelte VS Code 拡張機能](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode)のようなIDE拡張機能はエディタ上でエラーをキャッチするのに役立ちます。また、 [`svelte-check`](https://www.npmjs.com/package/svelte-check) はコマンドラインで同じことができ、CIに統合できます。 ## ` ``` これにより、 TypeScript の機能のうち _型のみ_ 使えます。つまり、型アノテーションやインターフェース宣言など、 JavaScript にトランスコンパイルすると消えてしまうすべての機能です。 TypeScript コンパイラが実際のコードを出力する必要のある機能はサポートされていません。これには以下が含まれます: - enumの使用 - コンストラクタ関数で `private`、 `protected` 、 `public` 修飾子を初期化子(initializer)といっしょに使用する - ECMAScript 標準の一部ではない(つまりTC39プロセスでレベル4ではない)ため、 JavaScript 解析に用いるパーサー Acorn 内に実装されていない機能の使用 これらいずれかの機能を使いたいときは、 `script` プリプロセッサをセットアップする必要があります。 ## プリプロセッサのセットアップ Svelte コンポーネント内で型以外の TypeScript 機能を使うには、 TypeScript を JavaScript に変換するプリプロセッサを追加する必要があります。 ```ts /// file: svelte.config.js // @noErrors import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { // `{ script: true }` の追加に注目してください preprocess: vitePreprocess({ script: true }) }; export default config; ``` ### SvelteKit または Vite の使用 もっとも簡単な TypeScript の始め方は、 `npx sv create` と入力してプロンプトに従い、TypeScriptオプションを選択して新しい SvelteKit プロジェクトの骨組みを自動生成することです。 ```ts /// file: svelte.config.js // @noErrors import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { preprocess: vitePreprocess() }; export default config; ``` SvelteKit が提供するすべての機能が必要ない、または望まないときは、代わりに `npm create vite@latest` と入力し、 `svelte-ts` オプションを選択することで、 Svelte 風味の Vite プロジェクトの骨組みを自動生成できます。 どちらの場合も、`vitePreprocess` を含む `svelte.config.js` が追加されます。 Vite または SvelteKit は、この設定ファイルを読み取ります。 ### ほかのビルドツール 代わりに Rollup や Webpack のようなツールを使っているときは、それぞれの Svelte プラグインをインストールしてください。 RollUpの場合は [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) 、 WebPackの場合は [svelte-loader](https://github.com/sveltejs/svelte-loader) です。両方とも、 `typescript` と `svelte-preprocess` をインストールし、プリプロセッサをプラグイン設定に追加する必要があります(詳細は各READMEを参照)。新しいプロジェクトを開始するときは、 [rollup](https://github.com/sveltejs/template) または [webpack](https://github.com/sveltejs/template-webpack) テンプレートを使って、スクリプトから初期設定を自動生成することもできます。 > [!NOTE] 新しいプロジェクトを開始するときは、代わりに SvelteKit または Vite の使用をおすすめします。 ## tsconfig.json の設定 TypeScript を使うときは、 `tsconfig.json` が正しく設定されていることを確認してください。 - クラスが関数にコンパイルされないように、 [`target`](https://www.typescriptlang.org/tsconfig/#target) を少なくとも `ES2015` 以降に設定してください。 - インポートがそのまま残るように、 [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) を `true` に設定してください。 - 各ファイルが個別に扱われるように、 [`isolatedModules`](https://www.typescriptlang.org/tsconfig/#isolatedModules) を `true` に設定してください。 TypeScript にはファイル間解析とコンパイルを必要とする機能がいくつかありますが、 Svelte コンパイラや Vite などのツールではこれをおこないません。 ## `$props` の型付け `$props` を、特定のプロパティを持つ通常のオブジェクトと同じように型付けします。 ```svelte ``` ## ジェネリックな $props コンポーネントのプロパティ間で、ジェネリクス(generics)を用いて型を関連づけることができます。例えば、汎用的なリストコンポーネントを考えてみましょう。このコンポーネントには、プロパティとして「アイテムのリスト」と「リストからアイテムを1つ受け取るコールバック関数」を渡すことができます。 そして、この `items` プロパティ(の配列)と `select` コールバック(の引数)が必ず同じ型であることを保証するために、 `script` タグに `generics` 属性を追加します。 ```svelte {#each items as item} {/each} ``` この `generics` 属性の書き方は、 TypeScript でジェネリック関数を定義するときの `<...>` (山括弧)内の構文とまったく同じです。言い換えると、複数のジェネリクス、 `extends` による型制約、デフォルトの型(フォールバック型)といった機能をそのまま利用できます。 ## ネイティブHTML要素をラップするコンポーネントの型付け コンポーネントを作るとき、ラップしたネイティブHTML要素( `button` など)の標準属性( `class` や `disabled` など)を、コンポーネントを使う側で自由に指定したい場合があるでしょう。そのときは `svelte/elements` が提供する型定義(インターフェース)を使用(または継承)してください。以下は `Button` コンポーネントの例です: ```svelte ``` すべての要素に専用の型定義が用意されているわけではありません。そのような要素には、 `SvelteHTMLElements` を使います: ```svelte
{@render children?.()}
``` ## `$state` の型付け `$state` はほかの変数と同じように型付けできます。 ```ts let count: number = $state(0); ``` もし `$state` に初期値を設定しない場合、その型は `undefined` とのユニオン型になります。 ```ts // @noErrors // エラー: 型 'number | undefined' を型 'number' に割り当てることはできません let count: number = $state(); ``` 変数の宣言時には値が決まっていなくても、後続の処理で _必ず_ 値がセットされる、とあなたが保証できるケースがあります。そのような場合は `as` キャストを使ってください。これはプロパティの初期化が `constructor` で行われるクラスで特に便利です: ```ts class Counter { count = $state() as number; constructor(initial: number) { this.count = initial; } } ``` ## コンポーネント自体の型 Svelte コンポーネントは `Component` 型です。 `Component` 型と関連する型を使って、さまざまな制約を表現できます。 例えば動的コンポーネントと組み合わせ、渡せるコンポーネントの種類を制限します: ```svelte ``` > [!LEGACY] Svelte 4 では、コンポーネントは `SvelteComponent` 型でした。 コンポーネントからプロパティを抽出するには、 `ComponentProps` を使います。 ```ts import type { Component, ComponentProps } from 'svelte'; import MyComponent from './MyComponent.svelte'; function withProps>( component: TComponent, props: ComponentProps ) {} // 第二引数が、第一引数のコンポーネントが期待するプロパティではないとき、 // エラーが発生します。 withProps(MyComponent, { foo: 'bar' }); ``` コンポーネントのコンストラクタまたはインスタンス型を期待する変数を宣言するには: ```svelte ``` ## 組み込みDOM型の強化 Svelteは、存在するすべてのHTML DOMの型をできる限り提供しています。しかし、場合によっては、実験的な属性やアクション (action) 由来のカスタムイベントを使いたいことがあるかもしれません。そのようなケースでは、 TypeScript はそれらの型を認識できないため、型エラーを発生させます。もしそれが(実験的でない)標準の属性やイベントである場合、 Svelte が提供する [HTMLの型定義](https://github.com/sveltejs/svelte/blob/main/packages/svelte/elements.d.ts) にその型が定義されていない可能性があります。そのときは、ぜひ issue を立てたり、修正のためのプルリクエストを送ってください。 もしこれがカスタムや実験的な属性・イベントであるときは、以下のように `svelte/elements` モジュールを拡張することで、型定義を強化できます: ```ts /// file: additional-svelte-typings.d.ts import { HTMLButtonAttributes } from 'svelte/elements'; declare module 'svelte/elements' { // Svelteが認識するHTML要素のリストに、新しい要素(ここでは'custom-button')を追加します export interface SvelteHTMLElements { 'custom-button': HTMLButtonAttributes; } // すべてのHTML要素で利用可能な新しいグローバル属性を追加します export interface HTMLAttributes { globalattribute?: string; } // 特定の要素(ここでは