関数なのかmethodなのかで変性が変わる
関数とmethodの引数は、defaultではbivariantである
しかし、methodの方はbivariantのままである
code: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であることで矛盾を起こす
例えば、こういう型があった時
code:ts
type SN = S|N
type S = string
type N = null
Arrayはcovariant
code:ts
const a2: SN[] = a1
ここでは、methodを持っていることを一旦無視すると納得できる
関数の引数の場合は、
code:ts
const push1 = (arg: S[]) => a1.push
// error
const push2: (arg: SN[]) => number = push1
引数の型はcontravariantなので、代入できない
しかし実際は、Arrayはclassであり、push()methodを持っている
code: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になっている