上級のTypeScriptエラー 24問
8種類のエラーを、それぞれ複数パターンずつ収録しています。
- Mapped typeも通常と同じ型チェックを受ける理由{ [K in keyof T]?: T[K] }のようなmapped typeで生成した型は、見た目は特殊でも、実体は通常のinterfaceと同じようにプロパティごとの型チェックが行われます。生成された型だからといって検査が緩くなることはありません。
- keyof typeofで作ったキーの型は、存在しないキーを渡すとエラーになるkeyof typeof objは、実行時のオブジェクトobjが実際に持つキーだけを表すunion型(リテラル型の集合)になります。定義時に存在しないキー文字列を渡すと、その型に含まれないためエラーになります。
- ジェネリクスのextends制約を満たさない型を渡すとエラーになる<T extends { length: number }>のように書くと、Tには「lengthプロパティを持つ型」しか渡せなくなります。制約を満たさない型(例えばnumber)を渡すと、呼び出し時点でエラーになります。
- 型注釈(: Type)はプロパティを消さずに「見えなく」する。satisfiesとの違い変数に: Typeという型注釈を付けると、その型に無いプロパティへのアクセスができなくなります。実行時にはプロパティ自体は残っていますが、型の上では「そんなものは無い」ものとして扱われます。satisfiesは元の値の型をそのまま保つため、この制限を受けません。
- 同名interfaceのマージで型が矛盾した原因と直し方同じ名前のinterfaceを複数回宣言すると、TypeScriptはそれらを自動的に1つに合成します(宣言のマージ)。ただし同じプロパティ名を違う型で宣言すると、合成できずにエラーになります。
- 変数経由なら余分なプロパティが通る理由オブジェクトリテラルを直接関数に渡すと余分なプロパティはエラーになりますが、いったん変数に代入してから渡すとエラーになりません。TypeScriptは「作られたばかり(フレッシュ)」なリテラルだけを厳格にチェックする設計になっています。
- as unknown as Xの二重キャストは型チェックを完全に迂回し、実行時エラーの原因になるTypeScriptは通常、明らかに無関係な型同士のasによるキャストをエラーにします。しかしunknownを経由する(as unknown as X)と、この安全装置を完全に迂回でき、どんな型にも変換できてしまいます。
- 数値enumはObject.keys()で要素数が2倍になる(逆引きマッピングの副作用)数値enumは、コンパイル後のJavaScriptオブジェクトに「メンバー名→値」だけでなく「値→メンバー名」の逆引きも自動的に持たせます。この副作用でObject.keys()を呼ぶと、メンバーの2倍の数のキーが返ってきます。