変数経由なら余分なプロパティが通る理由
オブジェクトリテラルを直接関数に渡すと余分なプロパティはエラーになりますが、いったん変数に代入してから渡すとエラーになりません。TypeScriptは「作られたばかり(フレッシュ)」なリテラルだけを厳格にチェックする設計になっています。
エラーメッセージの読み方
main.ts(9,26): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type 'Point'.
main.ts- ファイル名
9- 行番号
26- 列番号 — この位置でtscが検査に失敗しました
TS2353- エラーコード — 検索するとTypeScriptの解説が見つかります
Object literal may only specify known properties, and 'z' does not exist in type 'Point'.- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 interface Point { 2 x: number; 3 y: number; 4 } 5 const raw = { x: 1, y: 2, z: 3 }; 6 function printPoint(p: Point): void { 7 console.log(p.x, p.y); 8 } 9 printPoint({ x: 1, y: 2, z: 3 }); ^
main.ts(9,26): error TS2353: Object literal may only specify known properties, and 'z' does not exist in type 'Point'.
オブジェクトリテラルを直接渡すと余分なzプロパティがチェックされエラーになります。同じ内容でも変数raw経由で渡せばフレッシュネスチェックの対象外になります。
直し方: { x: 1, y: 2, z: 3 } を raw にします。
広告
広告スロット(未設定)
パターン2
1 interface Item { 2 name: string; 3 } 4 const raw = { name: "Pen", price: 100 }; 5 function printItem(i: Item): void { 6 console.log(i.name); 7 } 8 printItem({ name: "Pen", price: 100 }); ^
main.ts(8,26): error TS2353: Object literal may only specify known properties, and 'price' does not exist in type 'Item'.
リテラルとして直接渡すと余分なpriceがエラーになります。変数rawを経由して渡すとこのチェックは働きません。
直し方: { name: "Pen", price: 100 } を raw にします。
パターン3
1 interface Config { 2 host: string; 3 } 4 const raw = { host: "localhost", port: 8080 }; 5 function connect(c: Config): void { 6 console.log(c.host); 7 } 8 connect({ host: "localhost", port: 8080 }); ^
main.ts(8,30): error TS2353: Object literal may only specify known properties, and 'port' does not exist in type 'Config'.
直接のリテラルは余分なportをエラーにしますが、変数raw経由で渡せば同じ内容でもエラーになりません。
直し方: { host: "localhost", port: 8080 } を raw にします。
よくある誤解
「同じ内容のオブジェクトなら、渡し方が違っても結果は同じはず」という考えは、TypeScriptの構造的型付けには当てはまりません。リテラルとして直接渡すか、変数を経由するかで、チェックの厳しさそのものが変わります。
まとめ
変数経由なら余分なプロパティが通る理由は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。