事象
JavaScriptには 分割代入 という構文が存在する。この構文を使えば、Pythonライクにこのような書き方が可能になる。
function hogeFunc() {
return ["resA", 0];
}
const [val1, val2] = hogeFunc();
console.log(val1); // resA
console.log(val2); // 0
しかし、先程の例のval1, val2の型をそれぞれ見てみると、
おや?
hogeFuncが返しているリストの1番目はstring型の "resA"
であるため、当然val1もstring型と推論されて欲しいが、実際には string | number
と曖昧だ。
解説
この理由は、TypeScriptのリストにおける型の扱い方にある。TypeScriptで複数の型が代入可能な配列を定義する場合、
const multipleTypeList: (string | number)[] = ["resA", 0];
のようにパイプで型を区切って定義する。
今回の場合はこれと全く同じことが型推論によって起こっている。「multipleTypeListはstring型またはnumber型の変数を格納できる配列だ」と推論されるため、当然その1番目の型は string | number
となる。
対策
方法1. 関数をタプルで返すようにしよう
タプルは配列の一つ一つに型を定義できるものだ。
const multipleTypeList: [string, number] = ["resA", 0];
これを利用することで、先程の例はこのように書き換えられる
function hogeFunc(): [string, number] {
return ["resA", 0];
}
const [val1, val2] = hogeFunc();
console.log(val1); // resA
console.log(val2); // 0
方法2. 分割代入構文をやめて、大人しくオブジェクトを返すようにしよう。
オブジェクトならばタプルの型を定義するまでもなく適切に推論してくれる。
function hogeFunc() {
return {
val1: "resA",
val2: 0
};
}
const hogeValues = hogeFunc();
console.log(hogeValues.val1); // resA
console.log(hogeValues.val2); // 0