関数の引数は反変
S <: T
という関係の型 S
, T
がある時、
T -> () <: S -> ()
とする
この辺に書いているらしい
具体的に見る
Cat <: Animal
という関係の型について、 Animal -> ()
と Cat -> ()
の関係を見る
以下のどちらが型安全か?
Cat -> () <: Animal -> ()
Cat -> () :> Animal -> ()
後者の方が型安全。なぜか?
TypeScriptで具体的に見てみる
tstype 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"
を渡すと矛盾が生じるから