TypeScriptのArrayはinvariantではなくcovariantなので健全性が壊れている
例
code:ts
type Animal = Cat | Dog;
type Cat = 'cat';
type Dog = 'dog';
let animals: Animal[] = cats;
animals0 = 'dog'; // cats0とanimals0の中身が変わる console.log(cats0); // => "dog" 最終行
catsの型はCat[]のはずなのに、値を見ると'dog'になっている
invariantであるならば、let animals: Animal[] = cats;の部分でerrorが生じる
例えば、Scalaで同じコードを書いた例を見ると良い ref ちなみに、mrsekut.iconの場合はmutableな操作を一切書かないので、これが問題になったことはない
code:ts
interface 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
builtinのArray型は依然として壊れているが、それを拡張した型を定義すれば型安全にできる
上述したScalaと同じ位置で型errorを出せているmrsekut.icon
immutableであることを最初から前提にするなら
code:ts
let cats: readonly Cat[] = 'cat'; let animals: readonly Animal[] = cats;
animals0 = 'dog'; // error varianceの話ではないので、errorが生じる位置が異なることに注意mrsekut.icon