Code Fix

上級

変数経由なら余分なプロパティが通る理由

オブジェクトリテラルを直接関数に渡すと余分なプロパティはエラーになりますが、いったん変数に代入してから渡すとエラーになりません。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 にします。

この問題を解いてみる →

パターン4

 1  interface Coord {
 2    x: number;
 3  }
 4  const raw = { x: 1, y: 2 };
 5  function printCoord(c: Coord): void {
 6    console.log(c.x);
 7  }
 8  printCoord({ x: 1, y: 2 });
                      ^
main.ts(8,20): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type 'Coord'.

オブジェクトリテラルを直接渡すと余分なyプロパティがチェックされエラーになります。変数raw経由なら対象外になります。

直し方: { x: 1, y: 2 } を raw にします。

この問題を解いてみる →

パターン5

 1  interface Label2 {
 2    text: string;
 3  }
 4  const raw = { text: "hi", extra: true };
 5  function printLabel(l: Label2): void {
 6    console.log(l.text);
 7  }
 8  printLabel({ text: "hi", extra: true });
                            ^
main.ts(8,26): error TS2353: Object literal may only specify known properties, and 'extra' does not exist in type 'Label2'.

リテラルとして直接渡すと余分なextraがエラーになります。変数rawを経由すればこのチェックは働きません。

直し方: { text: "hi", extra: true } を raw にします。

この問題を解いてみる →

よくある誤解

「同じ内容のオブジェクトなら、渡し方が違っても結果は同じはず」という考えは、TypeScriptの構造的型付けには当てはまりません。リテラルとして直接渡すか、変数を経由するかで、チェックの厳しさそのものが変わります。

実務での勘所

この区別の背景には、リテラルを直接渡す場合と変数を経由する場合とで、余分なプロパティが「たぶん間違い」なのか「たぶん意図的」なのかの可能性が変わる、という設計上の判断があります。リテラルをその場で書いて直接渡す場合、そのオブジェクトは他のどこでも使われないため、余分なプロパティは典型的なタイプミスである可能性が高いと言えます。一方、変数に代入されたオブジェクトは、その型としてコード内の別の場所でも使われている可能性があり、余分に見えるプロパティが実は他の用途で正当に必要とされているのかもしれません。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)