TypeScriptのArrayはinvariantではなくcovariantなので健全性が壊れている
例
tstype Animal = Cat | Dog;
type Cat = 'cat';
type Dog = 'dog';
let cats: Cat[] = ['cat'];
let animals: Animal[] = cats;
animals[0] = 'dog'; // cats[0]とanimals[0]の中身が変わる
console.log(cats[0]); // => "dog"
最終行
cats
の型は Cat[]
のはずなのに、値を見ると 'dog'
になっている
invariantであるならば、 let animals: Animal[] = cats;
の部分でerrorが生じる
例えば、Scalaで同じコードを書いた例を見ると良い
refちなみに、

の場合はmutableな操作を一切書かないので、これが問題になったことはない
tsinterface InvariantArray<in out T> extends Array<T> {}
type Animal = Cat | Dog;
type Cat = 'cat';
type Dog = 'dog';
let cats: InvariantArray<Cat> = ['cat'];
let animals: InvariantArray<Animal> = cats; // error
animals[0] = 'dog';
console.log(cats[0]);
builtinの Array
型は依然として壊れているが、それを拡張した型を定義すれば型安全にできる
上述したScalaと同じ位置で型errorを出せている

immutableであることを最初から前提にするなら
tslet cats: readonly Cat[] = ['cat'];
let animals: readonly Animal[] = cats;
animals[0] = 'dog'; // error
console.log(cats[0]);
varianceの話ではないので、errorが生じる位置が異なることに注意
