generated at
関数なのかmethodなのかで変性が変わる
関数とmethodの引数は、defaultではbivariantである
strictFunctionTypes true にした時、関数の引数はcontravariantになる
しかし、methodの方はbivariantのままである


ts
// error let add: (n: number | null) => number; add = (n: number) => n + 10 // error type Func = { add: (n: number | null) => number } const f: Func = { add: (n: number) => n + 10 } // ok type Method = { add(n: number | null): number; } const m: Method = { add(n: number) { return n + 10 } };









構造的部分型と、関数の引数がcontravariantであることで矛盾を起こす
例えば、こういう型があった時
ts
type SN = S|N type S = string type N = null
Arrayはcovariant
ts
const a1: S[] = ['a','a'] const a2: SN[] = a1
ここでは、methodを持っていることを一旦無視すると納得できる
(この時点で、TypeScriptのArrayはinvariantではなくcovariantなので健全性が壊れているというのもあるがいったん置いておく)
関数の引数の場合は、
ts
const a1: S[] = ['a','a'] const push1 = (arg: S[]) => a1.push // error const push2: (arg: SN[]) => number = push1
引数の型はcontravariantなので、代入できない
しかし実際は、Arrayはclassであり、 push() methodを持っている
ts
let s = { push(arg: S[]) {} } let sn = { push(arg: SN[]) {} } // ok sn = s s = sn
以下の2点で矛盾する
Array<S> <: Array<SN>
push() を比較した場合は、contravariant
こちらを採用した場合は、 Array<S> >: Array<SN> になるはず
そのため、bivariantになっている