Programmingフロントエンド開発者

定数オブジェクトの型付けは、`as const`でどのように機能しますか?不適切な型付けによる利点や問題点は何ですか?

Hintsage AIアシスタントで面接を突破

回答

TypeScriptのas constは、オブジェクトや配列の値とプロパティをreadonlyおよびリテラル型に変換します。これにより、厳密な型付けが実現され、値は基本型に「拡張」されず、特定の値を保持します。

例:

const a = { status: 'success' }; // 型: { status: string } const b = { status: 'success' } as const; // 型: { readonly status: "success" }

利点:

  • 厳密な型付け (例えば、文字列に対するswitch/case、定数のリスト)
  • enumやReduxのactionTypes、ロールのリストに最適
  • 値の偶発的な変更を防ぐ

欠点/特徴:

  • プロパティはreadonlyになり、変更しようとするとエラーが発生します。
  • 注意深く使用しないと型の不整合を引き起こす可能性があります(例えば、文字列が必要なのにリテラルを渡した場合など)。

トリックのある質問

質問: 文字列の配列にas constを使用すると、その型はどうなり、通常のstring[]として渡すことはできますか?

回答: 型はreadonly ["a", "b", "c"]になります。つまり、readonly制約を持つリテラル型のタプルです。この配列はstring[]型と互換性がなく、可変の文字列配列を期待する場所に直接渡すことはできません。

const arr = ['a', 'b', 'c'] as const; // readonly ["a", "b", "c"] function acceptsStrings(x: string[]) {} acceptsStrings(arr); // エラー!型互換性なし

知識の欠如による実際のエラーの例


物語

プロジェクト: actionTypesのリストをas constで定数配列として保持し、その後string[]を待つ関数に渡そうとしました。型エラーが発生し、.slice()または[...arr]を使って明示的に変換する必要がありました。


物語

プロジェクト: Reduxのマイクロフレームワークで、action.typeの型をas constを使ってリテラルとして定義しました。switch-caseを実装する際、厳密な型付けを忘れ、すべての可能なリテラルを処理しなかったため、exhaustive checkが作動せず—新しいアクションを追加するまでエラーは発生しませんでした。


物語

プロジェクト: APIエンドポイントを自動生成する際に、そのキーをas const配列で記述しました。これらのキーを通常のRecord<string, ...>のインデックスとして使用しようとしたところ、型の不整合により失敗し、変換を追加するか、配列のキーの型を明示的に使用する必要がありました。