typescript について
開発者向けの TypeScript コードスタイルガイドです。型安全性、非同期 I/O、インポートとエクスポート、再利用、ログの規約を示します。
主な機能
- 01型安全性と型設計の規則
- 02非同期優先の I/O 指針
- 03インポート・エクスポート規約
- 04再利用可能なヘルパーの指針
- 05ログとエラー処理の規則
活用シーン
- 01新しい TypeScript モジュールの作成
- 02API のデータ形状に使う型の選定
- 03ファイルやサブプロセス I/O の追加
- 04インポート・エクスポート・ログのレビュー
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ lobehub/ lobehub --skill typescriptインストール後、Claude Code で/typescriptを入力して読み込まれたか確認します。
詳細
TypeScript コードスタイルガイド
型と型安全性
- TypeScript が型を推論できる場合は、明示的な型注釈を避けます
- 暗黙的な
anyを避け、必要に応じて明示的に型を指定します - 正確な型を使います。
objectやanyよりもRecord<PropertyKey, unknown>を優先します - オブジェクトの形状(React の props など)には
interfaceを、ユニオン型/交差型にはtypeを優先します - 単なる
as constよりもas const satisfies XyzInterfaceを優先します @ts-ignoreやas anyよりも@ts-expect-errorを優先します- 意味のない null/undefined パラメーターを避け、厳密な関数の契約を設計します
namespaceよりも ES モジュール拡張(declare module '...')を優先します。namespaceを使った拡張パターンは導入しないでください- 型に拡張性が必要な場合は、拡張フィールドをすべて 1 つのレジストリファイルに集約するのではなく、元の型の場所に小さなマージ可能なインターフェースを公開し、各機能/プラグインがローカルで拡張するようにします
PipelineContext.metadataのようなパッケージ内の拡張パターンでは、メタデータのフィールドを、それを読み書きするプロセッサー/プロバイダー/プラグインの近くに定義します
非同期パターン
- I/O では非同期を優先:新しい I/O コード(fs、child_process など)では、境界で非同期 API を使う必要があります。
import { readFile } from 'fs/promises'のような Promise ベースのものを使い、デフォルトでは*Syncを使わないでください。関数の色付けは非対称です。非同期から同期への移行は不要ですが、同期から非同期への移行では、I/O が遅くなったり、並行性が必要になったり、サブプロセス/ネットワーク呼び出しが追加されたりすると、呼び出し元をすべて上流まで書き換える必要が生じます。同期優先の負債は積み重なります。非同期処理の微小なコスト(スレッドプールのディスパッチ、キャッシュ競合)は正当な理由になりません。競合は、結果ではなく Promise をキャッシュすることで解決できます *Syncが許容されるのは、制御できない同期契約に呼び出し箇所が拘束されている場合に限ります。既存の同期シグネチャーチェーン(バグ修正でレガシーな同期チェーンを広範囲にリファクタリングしないでください。ただし、新しい独立モジュールでそのようなチェーンを延長してはいけません)、またはprocess.on('exit')のような同期専用コールバックが該当します。モジュール読み込み時や CLI 起動時の初期化は例外ではありません。その場合はトップレベルのawait(ESM)を使ってください
インポート
- リントで
simple-import-sort/importsとconsistent-type-importsを適用し、個別のimport type文を使います(fixStyle: 'separate-type-imports')。
コード構造
export defaultよりも 名前付きエクスポート を優先します。リファクタリング時の名前変更と IDE の自動インポートが同期され、import Foo from './foo'で発生するdefaultの名前変更の不整合を防げます。export defaultは、フレームワークで必須となるファイル(Next.js の page/route/layout、React.lazy の対象、vitest.config.tsのような設定ファイル)に限定してください。コードベースには今もexport defaultが多数ありますが、これは過去からの負債であり、踏襲するパターンではありません。上記のフレームワークで必須となるケース以外では、既存のexport defaultの使い方を新しいコードの手本にしないでください
再利用性
- ガード、パース、正規化、時間計測、JSON 安全なヘルパーを追加する前に、
packages/utilsとインストール済みパッケージを検索してください。機能ごとにヘルパーを重複して実装するのではなく、@lobechat/utilsまたは関連するサブパスを再利用します typeof value === 'object' && value !== nullのような、再利用可能なレコード/オブジェクトマップのガードを独自に実装しないでください。@lobechat/utils/objectからisRecord、isPlainRecord、isObjectLike、toRecord、pickString、UnknownRecordなどのヘルパーをインポートしますDate.now()は一度だけ定数に代入し、一貫性のために再利用します
ロギング
- ユーザーの個人情報(API キーなど)を決してログに記録しないでください
import { log } from 'debug'を直接使わないでください(コンソールにログが出力されます)- catch ブロックでは debug パッケージではなく
console.errorを使います .catch()コールバックでは必ずエラーをログに記録します。何もせずに.catch(() => fallback)とすると、失敗が握りつぶされ、デバッグが不可能になります
コメント
Markdown 対応