tldraw-migrate について
tldraw SDK を使うプロジェクトを新しいバージョンへ移行するスキルです。移行元と対象のバージョンを検出し、関連するリリースノートとドキュメントを取得して、パッケージ更新や TypeScript エラー、非推奨 API の修正を案内します。
主な機能
- 01移行元と対象のバージョンを検出
- 02変更履歴と SDK ドキュメントを取得
- 03導入済み tldraw パッケージを更新
- 04TypeScript エラーの修正を案内
- 05非推奨 API の使用箇所を検出
活用シーン
- 01最新の安定版 SDK への移行
- 02tldraw のプレリリース版への更新
- 03SDK 更新後の型エラーの解消
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tldraw/ tldraw --skill tldraw-migrateインストール後、Claude Code で/tldraw-migrateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignoredetect-target.mjsdetect-versions.mjsfetch-release-notes.mjsREADME.mdtype-errors.md詳細
tldraw 移行アシスタント
あなたは、プロジェクトを新しいバージョンの tldraw SDK へ移行する作業を支援します。以下のプロセスに注意深く従ってください。
このスキル全体を通して、${SKILL_DIR} はこのスキル自身のディレクトリ(SKILL.md、ヘルパーの .mjs スクリプト、キャッシュされた references/ フォルダーがある場所)を指します。以下の自動取得ブロックは、SKILL_DIR 環境変数が設定されていればそれから解決し、そうでなければ一般的なスキルの場所(.claude/skills/、.agents/skills/、.codex/skills/、.cursor/skills/、skills/)を探索します。ワークフローの後半で ${SKILL_DIR} を参照するシェルコマンドを実行するときは、同じ絶対パスに置き換えてください。このスキルを別の場所に配置した場合は、自動取得ブロックを実行する前に SKILL_DIR を設定してください。
引数: /tldraw-migrate [from-version] [target]。どちらも任意です。from-version は、git 履歴から検出された以前の tldraw バージョンがデフォルトになります。target は latest(npm 上の最新安定版リリース)がデフォルトです。プレリリースに移行するには、dist-tag(canary、next、beta)またはプレリリースの semver(例: 4.6.0-canary.abc123)を渡してください。
解決された移行: !SKILL_DIR="${SKILL_DIR:-$(for d in .claude/skills/tldraw-migrate .agents/skills/tldraw-migrate .codex/skills/tldraw-migrate .cursor/skills/tldraw-migrate skills/tldraw-migrate; do [ -d "$d" ] && printf %s "$d" && break; done)}" && FROM=$(node "$SKILL_DIR/detect-versions.mjs" $ARGUMENTS || true) && TARGET=$(node "$SKILL_DIR/detect-target.mjs" $ARGUMENTS) && if [ -z "$FROM" ]; then echo "ERROR: could not detect previous tldraw version. Pass it explicitly: /tldraw-migrate <from-version> [target]" >&2; else echo "from $FROM → target $TARGET"; fi
リソース(呼び出し時に自動取得)
以下の 3 つのブロックは、Claude Code の ! プレフィックスによる自動実行構文用に書かれています。これらの自動実行を行わないエージェント(Cursor、Codex、通常の Claude など)を使用している場合は、続行する前にそれぞれをシェルコマンドとして実行してください — これらは、以降のワークフローが依存する変更履歴、完全なドキュメント、および(プレリリースをターゲットとする場合は)次期リリースのノートをダウンロードします。
!SKILL_DIR="${SKILL_DIR:-$(for d in .claude/skills/tldraw-migrate .agents/skills/tldraw-migrate .codex/skills/tldraw-migrate .cursor/skills/tldraw-migrate skills/tldraw-migrate; do [ -d "$d" ] && printf %s "$d" && break; done)}" && mkdir -p "$SKILL_DIR/references" && CHANGELOG="$SKILL_DIR/references/tldraw-releases.txt" && PREV=$(node "$SKILL_DIR/detect-versions.mjs" $ARGUMENTS || true) && if [ -z "$PREV" ]; then echo "ERROR: could not detect previous tldraw version — skipping changelog fetch. Pass it explicitly: /tldraw-migrate <from-version> [target]" >&2; else node "$SKILL_DIR/fetch-release-notes.mjs" "$PREV" > "$CHANGELOG" && echo "Saved changelog (from $PREV, sourced from github.com/tldraw/tldraw) to $CHANGELOG ($(wc -l < "$CHANGELOG") lines)"; fi
!SKILL_DIR="${SKILL_DIR:-$(for d in .claude/skills/tldraw-migrate .agents/skills/tldraw-migrate .codex/skills/tldraw-migrate .cursor/skills/tldraw-migrate skills/tldraw-migrate; do [ -d "$d" ] && printf %s "$d" && break; done)}" && DOCS="$SKILL_DIR/references/tldraw-full-docs.txt" && STALE=$(find "$DOCS" -mtime +30 2>/dev/null) && if [ -s "$DOCS" ] && [ -z "$STALE" ]; then echo "Using cached full docs at $DOCS ($(wc -l < "$DOCS") lines) — delete the file or wait 30 days to refresh"; else curl --fail -sS https://tldraw.dev/llms-full.txt -o "$DOCS" && echo "Saved full docs to $DOCS ($(wc -l < "$DOCS") lines)"; fi
!SKILL_DIR="${SKILL_DIR:-$(for d in .claude/skills/tldraw-migrate .agents/skills/tldraw-migrate .codex/skills/tldraw-migrate .cursor/skills/tldraw-migrate skills/tldraw-migrate; do [ -d "$d" ] && printf %s "$d" && break; done)}" && mkdir -p "$SKILL_DIR/references" && TARGET=$(node "$SKILL_DIR/detect-target.mjs" $ARGUMENTS) && case "$TARGET" in canary|next|beta|alpha|rc|*-canary*|*-next*|*-beta*|*-alpha*|*-rc*) NEXT="$SKILL_DIR/references/tldraw-next.mdx" && curl --fail -sS https://raw.githubusercontent.com/tldraw/tldraw/main/apps/docs/content/releases/next.mdx -o "$NEXT" && echo "Pre-release target ($TARGET) — saved next-release notes to $NEXT ($(wc -l < "$NEXT") lines)" ;; *) echo "Stable target ($TARGET) — skipping next-release notes" ;; esac
- フィルタリング済み変更履歴 — 前回のバージョンから現在までの安定版のリリースノートで、
tldraw/tldrawの main にあるapps/docs/content/releases/から直接取得したものです(信頼できる情報源は tldraw.dev ではなく GitHub です)。各破壊的変更(💥でマークされています)には、変更前と変更後のレシピを示す<details><summary>Migration guide</summary>ブロックが付いています。これらのマイグレーションブロックは、バージョン固有の修正における主要な情報源です — このスキルは意図的にそれらを重複して記載していません。TS エラーに遭遇したら、このファイル内で該当する API 名を grep し、そのマイグレーションブロックを読んでください。 - 完全なドキュメント — tldraw SDK のドキュメント全体(約1.5MB)。これを最初に読まないでください。必要に応じて、特定のトピック(例: カスタムシェイプ、TLTextOptions)を検索するために Grep または行範囲を指定した Read を使用してください。
- 次期リリースノート — ターゲットがプレリリースの場合にのみ存在します。 次のバージョンに向けた進行中のリリースノート(
mainからの生の MDX)です。同じ<details><summary>Migration guide</summary>構造を持ちます。安定版の変更履歴では canary/next の差分をカバーしていません。それらはこのファイルで見つかります。
マイグレーションレシピの検索:
常に安定版の変更履歴と next.mdx の両方を grep してください(後者はプレリリースのターゲットにのみ存在します — 2>/dev/null がファイルが存在しないという警告を飲み込みます)。マイグレーションブロックは通常 40〜80 行にわたるため、デフォルトの後続コンテキストとして -A60 を使用してください。
# List every breaking change with a migration block
grep -nE '💥|<summary>Migration guide' ${SKILL_DIR}/references/tldraw-releases.txt ${SKILL_DIR}/references/tldraw-next.mdx 2>/dev/null
# Find the migration recipe for a specific symbol
grep -n -B2 -A60 'getIndicatorPath\|TLUserStore\|EmbedShapeUtil' ${SKILL_DIR}/references/tldraw-releases.txt ${SKILL_DIR}/references/tldraw-next.mdx 2>/dev/null
ステップ 1: 環境を理解する
変更を加える前に、プロジェクトをスキャンして、何を扱っているのかを理解してください。以下を並行して実行します:
- パッケージマネージャー: ロックファイル(
yarn.lock、pnpm-lock.yaml、bun.lockb、package-lock.json)を確認します。以降は対応するツールを使用してください。 - tldraw パッケージ:
grep -E "tldraw|@tldraw" package.json— どのパッケージがインストールされていて、どのバージョンですか? 注意: すべてのプロジェクトがすべての tldraw パッケージを使用しているわけではありません。 - ソースディレクトリ: プロジェクトの TypeScript ソースがどこにあるかを特定します(一般的には
src/、app/、lib/です。Next.js App Router のプロジェクトにはsrc/がありません)。以下のすべての grep にはこのディレクトリを使用してください —src/と決めつけないでください。 - インポートスタイル:
grep -r "from '@tldraw" <source-dir> --include="*.ts" --include="*.tsx" -l | head -5— プロジェクトは'tldraw'、'@tldraw/editor'、あるいはその両方からインポートしていますか? これはモジュール拡張のターゲットに影響します。 - TypeScript:
package.jsonにtypecheckまたはtscスクリプトがあるか確認します。どちらも存在しない場合は、npx tsc --noEmitにフォールバックします(TypeScript は通常 devDependency です)。TypeScript のバージョンも確認してください。 - ビルドツール:
package.jsonのスクリプトでビルドコマンド(vite、next、webpack、esbuild など)を確認します。 - リンター: oxlint/eslint/biome の設定ファイル(
.oxlintrc*、.eslintrc*、eslint.config.*、biome.json)を確認します。リンターは後で非推奨を検出するのに役立つ場合があります。 - モノレポ:
package.jsonは作業ディレクトリのルートにありますか、それともネストされたパッケージですか? ワークスペースの設定を確認してください。
ステップ 2: パッケージのアップグレード
検出されたパッケージマネージャーを使用して、プロジェクトの依存関係にすでに含まれているすべての tldraw パッケージを、解決されたターゲット(上記の「Resolved migration」行に出力されています)にアップグレードします。プロジェクトがすでに使用していない新しいパッケージは追加しないでください。
- 安定版ターゲット(
latestまたは安定版 semver)の場合: そのタグ/バージョンでインストールします。例:yarn add tldraw@latestまたはnpm install [email protected]。 - プレリリースターゲット(
canary、next、beta、またはプレリリース版 semver)の場合: そのタグ/バージョンでインストールします。例:yarn add tldraw@canary。複数の@tldraw/*パッケージがリストされている場合は、バージョンのずれを避けるために、すべてを同じターゲットに固定してください。
バージョンアップは単独でコミットしてください。 型を修正する前に、package.json とロックファイルのみをステージングしてコミットします。以降のステップによるソースコードの変更はそれぞれ独自のコミットに留めることで、最終的な git diff が依存関係の変更と混ざらず、「マイグレーションが何に触れたか」としてレビュー可能になります。
ステップ 3: すべての TypeScript エラーを特定する
プロジェクトの型チェックコマンド(ステップ 1 で確認)を実行し、エラーを分類します:
-
TS コード別にエラーを集計する(例: TS2344、TS2786)ことで、分布を把握します。
-
エラーが発生しているファイルを一意にリストアップすることで、影響範囲を把握します。
-
エラーパターンを特定します。 以下のカテゴリはバージョンに依存しません — 一般的なエラーの形を説明するものです。各リネーム、削除、シグネチャ変更に対する具体的な修正方法は、このスキルではなく、リリースノートのマイグレーションブロック(上記の「マイグレーションレシピの検索」を参照)に記載されています。
- TS2786「cannot be used as JSX component」/「bigint not assignable to ReactNode」: React の型のずれです。
@types/react(および通常は@types/react-dom)が tldraw がバンドルするバージョンと一致していません。バンドルされているバージョンを見つけるには: npm または yarn classic の場合はnode_modules/@tldraw/editor/node_modules/@types/react/package.jsonを確認します。pnpm または yarn berry の場合は、パッケージマネージャーの「why」コマンド(例:pnpm why @types/react)を実行します。 - TS2344「does not satisfy constraint TLShape/TLBaseBoxShape」/ TS2416
shapeTypeの不一致: カスタムシェイプまたはバインディング型が、新しいグローバル props マップに登録されていません。修正パターンは 4b にあります。 - TS2305 / TS2724「has no exported member」/「is not exported」: API が削除またはリネームされました。
tldraw-releases.txt/tldraw-next.mdx内の対応するMigration guideブロックで置き換えを探してください。 - TS2339「property does not exist」: API がリネームされたか、メソッドのシグネチャが変更されました。同じく上記の参照で探してください。
- TS2515「non-abstract class does not implement inherited abstract member」: 基底クラスに必須メソッドが追加されました。エラーにそのメソッド名が表示されるので、マイグレーションブロックでそのメソッド名を検索してください。(注意: 実装が throw するだけの場合、TypeScript が
neverと推論することがあります。基底クラスのシグネチャを満たすために明示的な戻り値の型を追加してください。) createShapes/updateShapesにおける TS2345: 異種のマップ済み配列にはas TLShapePartial[]/as TLCreateShapePartial[]のキャストが必要です。4e を参照してください。- 構造的に類似した 2 つの
Editorクラスがnode_modules/@tiptap/coreとnode_modules/@tldraw/editor/node_modules/@tiptap/coreの下で異なるパスに解決される場合の TS2345: TipTap v2/v3 の二重インストールです。4d を参照してください。
- TS2786「cannot be used as JSX component」/「bigint not assignable to ReactNode」: React の型のずれです。
ステップ 4: 影響の大きい順にエラーを修正する
この順序で修正します。各修正は、後続の多くのエラーを解消します。各サブステップの後で型チェックを再実行し、そのサブステップが対象とするエラーコードが解消されたか、減少していることを確認してください。無関係なコードは無視します。それらは後のサブステップに属します。
| サブステップ | 症状 |
|---|---|
| 4a. React の型 | TS2786「bigint を ReactNode に割り当てることができません」 |
| 4b. カスタムシェイプとバインディング | TS2344 の制約エラー、TS2416 の shapeType の不一致 |
| 4c. API の名前変更、削除、抽象メソッド | TS2305、TS2724、TS2339、TS2515 |
| 4d. TipTap のインポート | プロジェクトが @tiptap/* に依存している場合のみ — それ以外はスキップ |
| 4e. 残りの型エラー | .map() を伴う createShapes/updateShapes、残ったキャスト |
プロジェクトに実際に存在するコードに応じた手順については、type-errors.md を参照してください。最初から最後まで読むのではなく、該当するサブステップにジャンプしてください。
ステップ 5: 非推奨の修正
すべての型エラーが解消されたら、@deprecated の API 使用箇所を見つけて修正します。これらはまだコンパイルできますが、移行する必要があります。
-
非推奨のシンボルを見つけます。 変更履歴が出発点として最も信頼できます — tldraw の
.d.tsファイルは複数行の JSDoc を使用しているため、型定義を grep するのは脆弱です(宣言行は通常、@deprecatedタグの 2〜5 行後にあり、隣接していません)。ここから始めます:
grep -i 'deprecated' ${SKILL_DIR}/references/tldraw-releases.txtターゲットがプレリリースの場合は、さらに:
grep -i 'deprecated' ${SKILL_DIR}/references/tldraw-next.mdx。型定義と照合するには(一度に 1 パッケージずつ — プロジェクトがインポートしている各
@tldraw/*パッケージ、およびtldraw自体について繰り返します)、-Bではなく-Aを使用します:grep -A5 '@deprecated' node_modules/@tldraw/editor/dist-cjs/index.d.ts \ | grep -oE '\b(class|function|interface|const|type|let|var)\s+\w+' \ | awk '{print $NF}' | sort -uこれは複数行の JSDoc を捉えますが、いくつかの誤検出を生じます。出力は候補リストとして扱い、権威あるものとはみなしません。駆動すべきは変更履歴の grep です。
-
設定されている場合はリンターを実行します — 非推奨ルール(例: eslint の
deprecation/deprecation)は、非推奨のインポートを自動的に指摘します。リンターが設定されていない場合は、このステップをスキップします。 -
プロジェクトのソースで 各非推奨シンボルを検索します。
@deprecatedの JSDoc コメント、変更履歴のエントリ、またはドキュメントにある推奨の代替手段に置き換えます。 -
型チェックが捉えなかった名前変更を再確認します。 変更履歴または
tldraw-next.mdxが名前変更について記述していて、プロジェクトがまだ古い名前をインポートしている場合、TypeScript はワイルドカードの再エクスポートを通じてそれを解決し、見逃す可能性があります。変更履歴/next.mdx で「renamed」/「moved to」のエントリをざっと確認し、見つけた古い名前をソースで grep します。
ステップ 6: 検証
プロジェクトの型チェックコマンドとビルドコマンドを実行します(ステップ 1 で確認したとおり)。
エラーが残っている場合は、分類と修正のサイクルを繰り返します。
移行後の健全性チェック
すべてのエラーが解消されたら、簡単な監査を行います。
-
この移行で追加された型付き
asキャストを数えます。 素朴なgrep ' as 'はas const(推奨される絞り込みパターン)やインポートパス内のasも含んでしまうため、過大にカウントします。diff を基にフィルタリングしてください。git diff -- '<source-dir>/**/*.ts' '<source-dir>/**/*.tsx' \ | grep -E '^\+' | grep -v '^+++' \ | grep -E '\bas\s+[A-Z]' | grep -v 'as const'移行で追加すべき新しい型付きキャストはごくわずかです(理想的にはゼロで、異種の
createShapes/updateShapes配列に対するas TLShapePartial[]/as TLCreateShapePartial[]が主要な正当な例外です)。移行全体で ~5 個を超えて追加した場合は、戻って修正してください。ほぼ間違いなく、新しい API を誤って使用しています。 -
追加したすべての型付きキャストをレビューします: それぞれについて、
as const、satisfies、ジェネリック型パラメータ、またはモジュール拡張で置き換えられないかを確認し、本当に必要かどうかを検証します。よりクリーンな代替手段があるものは削除または置き換えてください。 -
モジュール拡張を監査します。 モジュール拡張は
TLGlobalShapePropsMap/TLGlobalBindingPropsMapの登録や、本当に不足している公開型を追加する場合には正しい方法です。SDK が@internalに降格したシンボルを再公開する場合には正しくありません — それは修正ではなく回避策です。代わりに公開された代替手段を見つけてください(通常、移行ブロックにその名前が記載されています)。 -
スタブやデッドコードがないことを確認します: 削除された API をスタブ化した場合(例: 削除された関数を no-op に置き換えた)、呼び出し側のコードが戻り値に依存していないことを確認してください。依存している場合は、移行ブロックまたはドキュメントで適切な代替手段を見つけてください。
ステップ 7: レポート
移行の最後に、ユーザーへ単一のサマリーメッセージを送ります。水増しせず、事実だけを記載します:
- 移行元 → ターゲットバージョン、およびタグだった場合は解決後のターゲットバージョン(
canary→4.7.0-canary.abc123)。 - 変更したファイル(件数、少なければリストも)。
- 修正した TypeScript エラー、コード別の内訳(例:
TS2786 ×12、TS2344 ×3、TS2305 ×1)。ステップ 4 で収集した before/after の件数を使用してください。 - 追加した型付き
asキャスト(件数と各キャストの一行の根拠 — ゼロまたはゼロに近いはずです。確信が持てなかったものにはフラグを立ててください)。 - 追加したモジュール拡張(対象となるもの —
TLGlobalShapePropsMap、TLGlobalBindingPropsMap、@tiptap/coreチェーンコマンドなど)。 - 移行した非推奨項目(件数とシンボル)。
- 文書化されていないとしてフラグを立てたもの — どの移行ブロックにも見つからなかったシンボル、変更履歴の抜け、または実際の API サーフェスと一致しなかったレシピ。これらは tldraw チームにフィードバックする価値があります。
- スキップまたは先送りしたもの — 難しいリネームを見送ったり
TODOを残した場合は、何がまだユーザーの手元にあるかを明確にするため、明示的に記載してください。
品質チェック
- 型安全性が最優先です。 目標は、元のコードと同程度に型安全な移行です。
as any、as unknown、または広範な型キャストを追加しないでください。@ts-ignoreや@ts-expect-errorも追加しないでください。これらは決して許容されません — 型をうまく通せないなら、まだ新しい API を理解できていないということです。いったん止まり、続ける前に変更履歴と型定義を読んでください。 - キャストよりも TypeScript の絞り込み機能を優先してください。 リテラル型には
as const、型を広げずに型チェックするにはsatisfies、呼び出し側にはジェネリックパラメータ、インターフェースの拡張にはモジュール拡張を使用します。これらが移行における適切なツールです —asキャストはそうではありません。 - 同じパターンの大きなバッチには並列エージェントを使用してください。 まず 1 つのファイルに手作業でレシピを適用して動作を確認し、その後、残りのファイルごとに 1 つの Agent を 1 つのメッセージ内で起動します (複数の Agent ツール呼び出しを並列で)。各エージェントには次を渡します: (1) 移行するファイルのパス、(2) テンプレートファイルの before/after 差分、(3)
tldraw-releases.txtの該当する移行ブロック。これは 4b (多数のシェイプファイルにまたがる機械的なTLBaseShape→TLGlobalShapePropsMapの移行) と 4c (プロジェクト全体に波及する 1 つのシンボル名の変更) で最も役立ちます。 - エラーを消すだけでなく、新しい API を理解してください。 メソッドのシグネチャが変わったとき (例: 新しいパラメータの追加、プロパティがよりリッチな型に改名)、変更された 理由 を理解するために変更履歴と現在の型定義を読んでください。コンパイルは通るものの、新しい API が実データを期待している箇所にハードコードされた値やダミー値を渡す修正は、型エラーよりも悪いです — それは気付かないうちに動作を劣化させます。たとえば、関数に新しい必須パラメータが追加された場合は、
0や1を渡すのではなく、どのシェイププロパティやエディタの状態がそれらのパラメータに渡されるべきかを確認してください。 - API パターンについて不明な場合は、その特定の API の使用例を完全なドキュメント (
${SKILL_DIR}/references/tldraw-full-docs.txt) で grep してください。ドキュメントには、各 API の正規の使い方を示すコードサンプルが含まれています。
ヒント
- フィルタリングされた変更履歴については
${SKILL_DIR}/references/tldraw-releases.txtを読んでください — これが何が変わったかの主要な情報源です - 特定の API に関するドキュメントが必要なときは
${SKILL_DIR}/references/tldraw-full-docs.txtを grep してください - tldraw の型を検索するときは、複数のパスを試してください — dist ディレクトリの構造はバージョンとパッケージマネージャーによって異なります