関数の引数は反変
S <: Tという関係の型S,Tがある時、
T -> () <: S -> ()とする
この辺に書いているらしい
具体的に見る
Cat <: Animalという関係の型について、Animal -> ()とCat -> ()の関係を見る
以下のどちらが型安全か?
Cat -> () <: Animal -> ()
Cat -> () :> Animal -> ()
後者の方が型安全。なぜか?
TypeScriptで具体的に見てみる
code:ts
type Animal = Cat | Dog;
type Cat = 'cat';
type Dog = 'dog';
const P: React.FC = () => {
return <C fn={(c: Cat) => true} />; // error
};
const C: React.FC<{ fn: (a: Animal) => boolean }> = ({ fn }) => {
const is = fn('dog'); // 引数はAnimal型なので、"dog"を渡せる
return <div></div>;
};
直観とズレている部分を確認しておくと、
(a: Animal) => booleanに対して、(c: Cat) => boolean渡せそうじゃない?という点
実際は渡せなくて型errorが生じる
まず子Component Cの中を見る
Cの中は正しく完結している
propsで得られるfnの引数はAnimalなので、"dog"に適用しても問題ない
次に、Pを見る
Cに対して、Catが引数の関数を渡している
ここでerrorになる
これはerrorになるべきで、上で見たCの中で"dog"を渡すと矛盾が生じるから