TypeScript は structural typing(「ダックタイピング」)を採用しています。2 つの型は、その名前や宣言された場所に関係なく、**同じ形状(shape)**を持っていれば互換性があります。これは、互換性が宣言された型名に依存する nominal な型付け(Java、C#)とは対照的です。
ts
{ : ; : ; }
() { .(p., p.); }
obj = { : , : , : };
(obj);
TypeScript は structural typing(「ダックタイピング」)を採用しています。2 つの型は、その名前や宣言された場所に関係なく、**同じ形状(shape)**を持っていれば互換性があります。これは、互換性が宣言された型名に依存する nominal な型付け(Java、C#)とは対照的です。
{ : ; : ; }
() { .(p., p.); }
obj = { : , : , : };
(obj);
obj は Point として宣言されていませんが、形状の上で 構造的に その shape を満たしているため受け入れられます。既存の変数を渡す場合は、余分なプロパティが許可されます。
print({ x: 1, y: 2, z: 3 }); // ❌ Error: 'z' does not exist in type 'Point'
オブジェクト リテラル を直接渡す場合は、タイプミスを捕捉するためのより厳格な「余剰プロパティチェック(excess property check)」が適用されます。しかし、いったん変数に代入してから渡せばチェックを通過します。これは柔軟性と間違いの捕捉との間の意図的なバランスです。
structural typing は TypeScript を柔軟で扱いやすいものにします。interface を明示的に実装しなくてもそれを満たすことができ、これは JavaScript のオブジェクトリテラルのスタイルに適しています。
トレードオフとして、たまたま同じ shape を共有する型は、概念的に無関係であっても交換可能になってしまいます(nominal に近い区別が必要なときに branded types を使う理由の 1 つです)。