【TypeScript】ArrayにObjectが代入できてしまう問題に気をつけよう

フロントエンド

はじめに

コードレビューをしていて不思議なコードにであったので紹介です。

typescriptを使っているから型は安全だろうと思い込んでいたら、そうではなかったという経験談になります。
なぜ、これで型チェックが通るのか不明ですが、盲目的になるのはよくないようです。

現象

以下のようなコードがあります。
( 実際にレビューをしたコードではなく、問題が分かりやすいように簡素化してます。 )

type MyArray = number[];
const array: MyArray = [1, 2, 3];

そして、以下のコードが本題です。

// why pass tsc

const array2: MyArray = {
  ...array,
};

実際にarray2には配列ではなくオブジェクトが格納されています。

今回の場合、配列をスプレッド構文で展開し、オブジェクト化させることができたことが問題なのではなく、
MyArrayに対し、オブジェクトを代入できたことが問題だと考えています。

スプレッド構文を用いて配列をオブジェクトに変換した際は以下のような挙動になります。
( ちなみにこの時、型は自動推論され{ [x: number]: number; }となってくれます。 )

const array = [1, 2, 3]
console.log({ ...array })

/* output
  {
    0: 1,
    1: 2,
    2, 3
  }
*/

原因

わからないです。。。
( 連想配列だから内部的には配列ってことなのかな。。。 )
配列もオブジェクトも以下のように各要素にアクセスできるので、一見エラーは出ないです。
ただし、mapは使えないので、React等を使っていると普通にエラーが発生します。

type MyArray = number[];
const array: MyArray = [1, 2, 3];
const array2: MyArray = { ...array };

// ok
console.log(array2[0]);

// error 
array2.map(value => {  /* do something */ })
// => Uncaught TypeError: array2.map is not a function

自分の興味と熱量がある内は原因を調べてみますが、ご存知の方は教えてくださると助かります。
( please tell me why is happens, if you know )

対策

マンパワーで解決以外思いつかない。
あとはobjectのkeyにはnumberは使わないとか?
( でも線形走査するくらいならobject使うってケースあるからな。。 )

タイトルとURLをコピーしました