generated at
Optional Variance Annotations for Type Parameters
v4.7から in / out を用いてvarianceを明示できる



Getter 型をcovariantとする場合は、型引数に out を書く
ts
type Getter<out T> = () => T;
この T を引数で使おうとするとerrorになる
ts
type Getter<out T> = (a: T) => T; // error
Setter 型をcontravariantにする場合は、型引数に in を書く
ts
type Setter<in T> = (value: T) => void;
State 型をinvariantにする場合は、 in out T と書く
ts
type State<in out T> = { get: () => T; set: (value: T) => void; }
こうすると State はinvariantになる
雑に言えば、 State<Cat> State<Animal> のような型の間に部分型関係がなくなる
ちなみに逆順で out in とは書けないmrsekut



構造的部分型にvarianceは重要ではないが、導入された理由 ref
読み手が理解するのに役立つ
その型のvarianceが即座にわかる
その型の型変数が使われる場所の意図が読める
推論のパフォーマンス向上につながる
TypeScriptは最適化としてvarianceを推論するが、その速度が上がる
推論に失敗することもあるので、その補助になる
例えば、深い相互再帰などがある場合 ref








書ける状況はかなり制限されているっぽい

関数の定義時には書けないのかmrsekut
ts
function add<in T>(arr: Array<T>) { return [...arr, 'hoge']; }


これ、関数型にしか使えないのか?
以下のようには書けない?
ts
type InvariantArray<in out T> = Array<T> // error
Variance annotations are only supported in type aliases for object, function, constructor, and mapped types
書けないらしい
というか type で定義した時は制限があるという感じかmrsekut
interfaceを使えば書ける
ts
interface InvariantArray<in out T> extends Array<T> {}