Upgrade to Pro — share decks privately, control downloads, hide ads and more …

declaration mergingの威力:ライブラリアップデート時の書き換え作業を90%短...

declaration mergingの威力:ライブラリアップデート時の書き換え作業を90%短縮するテクニック

TSKaigi2025のLT資料です。
https://2025.tskaigi.org/talks/yutake27

zennに詳しい解説もしています
https://zenn.dev/atamaplus/articles/fccdb3265dea8c

Avatar for Yuma Takei

Yuma Takei

May 24, 2025
Tweet

Other Decks in Technology

Transcript

  1. 手作業対応だと難しいライブラリアップデートのケース UI ライブラリのバージョンアップに伴う問題 この UI ライブラリの Button コンポーネントには disabled とisDisabled

    の2つのプロパティが定義されている // どちらも利用可能 <Button disabled={true} /> <Button isDisabled={true} /> disabled を使うように統一していたが、 あるバージョンから isDisabled を使わないと挙動がデグレすることがわかったので、 全てisDisabled に書き換える必要が発生 <Button disabled={true} /> // 型エラーは起きないが動作しない しかし disabled が型定義から削除されなかったため、 disabled を使っている箇所を型レベルでは検出できず困った 5
  2. 検討した案と解決策 1. 人力で置換する デメリット:時間がかかる、漏れが発生する可能性がある、今後の使用禁止ができない 2. ラッパー(腐敗防止層)を作成する メリット:ラッパー内部で変換処理を行うだけで済む デメリット:既存コードの置き換え作業コストが高い 3. declaration

    mergingを使って型の上書きをして古いプロパティの使用を禁止し、 新しいプロパティに置き換える メリット:型レベルで古いプロパティの使用を禁止でき、使用箇所は型エラーで検出できる デメリット:型安全性を保っていない部分は検出できない → 3 の declaration merging を使った案を採用 6
  3. declaration merging とは 同じ名前の interface を複数定義すると宣言が merge される機能 interface User

    { name: string; } interface User { age: number; } // 以下と同義 interface User { name: string; age: number; } この機能を利用して、ライブラリの型定義を上書き可能 never 型で型定義を上書きすることで、使用箇所で型エラーを発生させることが可能 7
  4. 置き換え手順 1: 型定義の上書き 型定義ファイルを作成してライブラリの型定義を上書き // @ui-library.d.ts export * from "@ui-library";

    // ライブラリの型解決のために必要 declare module "@ui-library" { export interface ButtonProps { disabled?: never; // 上書きしたい型をnever で上書き } } 期待される結果 置き換えたいプロパティを使用している箇所で型エラーが発生 型チェックを実行すると、修正が必要な箇所を一覧化可能 補足 export * from '@ui-library' は必須(型解決のため) never 型を使用することで、そのプロパティの使用を禁止 optional にしているのは元々 disabled が optional プロパティのため 10
  5. 置き換え手順 2: プロパティ名の変更 エディタのリファクタリング機能でプロパティ名の変更 期待される結果 プロジェクト全体でプロパティ名が一括置換される - <Button disabled={true}> クリック</Button>

    + <Button isDisabled={true}> クリック</Button> ※ ただし変数経由でプロパティを設定している箇所は置換されない const props = { disabled: true }; // 置換されない <Button {...props} />; 11
  6. 置き換え手順 3: 動作確認 1. ライブラリをアップデート 2. 型エラーの確認 型チェックを実行して型エラーがないか確認 エラーが発生している箇所(変数経由でプロパティを設定している箇所)を手動で修正 3.

    テストの実行 型安全性でない部分(any 型など)は置き換え漏れを検出できないのでテストが必要 弊社では 120 箇所程度の利用箇所のうち自動置き換えできなかったのは 5 箇所ほど 型安全性を保っておくことは重要! 12