TL;DR

型の名前ではなく、型が持つメンバー(構造)で型どうしの互換性を判断する考え方。型の名前で判断する名前的型付けと対になる。TypeScript が採用している。

なぜ必要か

TypeScript Handbook によると、TypeScript は JavaScript の書き方に合わせて設計されている。JavaScript では無名のオブジェクトや関数式を多く使うので、構造で関係を判断するほうが自然である。Effective TypeScript 項目4 では、TypeScript が構造的型付けで JavaScript のダックタイピングをモデリングしていると説明している。

仕組み

TypeScript Handbook の基本ルールでは、y が少なくとも x と同じメンバーを持っていれば、x は y と互換性がある。

例

interface Pet {
  name: string
}
class Dog {
  name: string
}
let pet: Pet = new Dog() // Dog は Pet を実装すると宣言していないが、代入できる

注意点

Effective TypeScript 項目4 によると、構造的型付けでは、値が型宣言にないプロパティを持っている可能性がある。TypeScript では宣言したプロパティだけを持つ「閉じた型」を表現できないので、オブジェクトのプロパティを反復処理するときに予期しない挙動になりやすい。名前で型を区別したいときは Branded Types を使う。

関連

出典