項目25 進化する型を理解する
TypeScriptでは、変数の型は宣言時に確定され、その後、型を絞り込むことは可能だが新しい値を含むよう型を拡張することはできない
ただ、上記には例外があり、進化する型が存在する
進化する型
進化する型の特徴
書き込むときだけany型になる
any型のまま読もうとするとエラーになる
[]で初期化された型が進化するケース
code:ts
function range(start: number, limit: number) {
const nums = []; // const nums: any[]
for (let i = start; i < limit; i++) {
nums.push(i);
}
return nums; // const nums: number[] 宣言時と比較して型が進化している
}
空の配列の型は、異なる要素を追加することで大きくできる
code:ts
const result = []; // const result: any[]
result.push('a');
result // const result: string[]
result.push(1);
result // const result: (string | number)[]
条件分岐では、条件ごとに型が変わる
code:ts
let value; // let value: any
if (Math.random() < 0.5) {
value = /hello/;
value // let value: RegExp
} else {
value = 12;
value // let value: number
}
value // let value: number | RegExp
変数の初期値がnull、undefinedの場合に進化するケース
try ~ catchで値をセットするときによく起こる
code:ts
declare function doSomethingRiskyAndReturnANumber(): number;
let value = null; // let value: any
try {
value = doSomethingRiskyAndReturnANumber();
value // let value: number
} catch (e) {
console.warn('alas!');
}
value // let value: number | null
変数が暗黙的にany型を持つため、「進化するany」と呼ばれることもあり、これは危険なanyではない
進化するletや進化する配列と呼ばれることもある
進化する型は、型アノテーションを減らす際に有効
配列に要素をpushする、条件付きで値をセットするときは、進化する型を使って型アノテーションを減らす。
⚠️進化する型を利用する際の注意点
その進化はほんとに正しいのかどうか気を配る
意図しない進化が行われる場合は、型アノテーションを使って型を補足する