関数型の互換性(引数)【個人学習まとめ】
関数型の互換性(反変)
前回の記事では戻り値の型に関する互換性(共変)を学習しました。
今度は引数の型について学習します。できるだけ単純にするために、戻り値の型に互換性があると仮定して確認してみましょう。
引数の型
実際に確認する前に、引数の型となる 2 種類のインターフェイスPersonとTeacherを定義します。
interface Person {
name: string;
age: number;
}
interface Teacher extends Person {
subject: string;
}
TeacherインターフェイスはPersonインターフェイスを拡張しています。
そのため、Teacherがもつプロパティは
nameagesubject
の 3 つになり、TeacherはPersonのサブタイプという関係が成立します。
互換性を確認するためにfunction3とfunction4という関数型の変数と確認用の引数を用意します。
let function3 = (person: Person) => {
console.log("---- function3 ----");
console.log(`名前:${person.name}`);
console.log(`年齢:${person.age}`);
};
let function4 = (teacher: Teacher) => {
console.log("---- function4 ----");
console.log(`名前:${teacher.name}`);
console.log(`年齢:${teacher.age}`);
console.log(`部活:${teacher.subject}`);
};
//確認用の引数
const personTestData: Person = { name: "テスト太郎", age: 10 };
const teacherTestData: Teacher = {
name: "先生 太郎",
age: 20,
subject: "国語",
};
function3の引数はPerson型、function4の引数はTeacher型です。
それぞれ戻り値はありません。
これまでの学習から、Person型とTeacher型は互換性があるのでfunction3にfunction4が代入できるのではないか?と思いますよね。試してみましょう。

エラーとなりました。なぜでしょうか?
function3は引数としてPerson型を受け取る関数ですが、実際にはfunction4の引数Teacher型を受け取る必要があります。
そのため**function4ではPerson型には存在しないsubjectプロパティにアクセスを試みる**ことになりますが、subjectプロパティが存在しないためエラーとなります。
では逆にfunction4にfunction3は代入できるのでしょうか。

エラー無く代入することができます。
function4にfunction3を代入後function4を呼び出す際には、引数としてTeacher型のオブジェクトを渡す必要があります。
この時、function4にはfunction3が代入されているため、実際には**function3にTeacher型の引数が渡され**実行されます。
function3に渡される引数Teacherにはfunction3には必要のないsubjectプロパティが存在しますが、function3内部でsubjectにアクセスしていないため、無視されることになります。
さいごに
2つの記事で関数の互換性(共変・反変)について学習しました。
自分なりにかみ砕いて説明したつもりですが、なかなか難しい内容になってしまいました。(要改善な気がします・・・)
難しい内容でしたが「共変・反変」という正しい名前を知ることができ、勉強になりました。
新たな発見にもつながるので、間違いがあればご指摘いただけるとありがたいです!
Discussion