かなり一般的に、JavaScriptのコードベースでは、以下のようにしてオブジェクトリテラルを初期化します。
let foo = {};
foo.bar = 123;
foo.bas = "Hello World";
コードをTypeScriptに移すと即座に次のようなエラーが表示されます。
let foo = {};
foo.bar = 123; // Error: Property 'bar' does not exist on type '{}'
foo.bas = "Hello World"; // Error: Property 'bas' does not exist on type '{}'
これは、let foo = {}
の状態から、TypeScriptはfoo
の型(初期化代入の左辺)を右辺{}
の型に推論するためです(プロパティの無いオブジェクト)。そのため、あなたがTypeScriptが知らないプロパティに代入しようとするとエラーになります。
TypeScriptでオブジェクトを初期化する適切な方法は、代入でそれを行うことです。
let foo = {
bar: 123,
bas: "Hello World",
};
これは、コードのレビューと保守性の意味でも適しています。
以下で説明する簡単な修正と、妥協的な遅延初期化パターンは、プロパティを初期化すること忘れることに苛まれます。
TypeScriptに移行するJavaScriptコードベースが大きい場合は、理想的な修正が実行可能な解決策ではない可能性があります。その場合、_型アサーション_を慎重に使用してコンパイラをサイレントにすることができます:
let foo = {} as any;
foo.bar = 123;
foo.bas = "Hello World";
もちろん、any
アサーションを使用することは、TypeScriptの安全性を損なうため、非常に悪いことがあります。妥協的なfixは、インターフェースを作り、以下を確実にすることです。
- 良いドキュメント
- 安全な代入
これを以下に示します。
interface Foo {
bar: number
bas: string
}
let foo = {} as Foo;
foo.bar = 123;
foo.bas = "Hello World";
インターフェースを使用するとバグから救われるという事実を示す簡単な例です:
interface Foo {
bar: number
bas: string
}
let foo = {} as Foo;
foo.bar = 123;
foo.bas = "Hello World";
// later in the codebase:
foo.bar = 'Hello Stranger'; // Error: You probably misspelled `bas` as `bar`, cannot assign string to number
}