TypeScriptのコンパイルエラー回避方法(備忘録)

# はじめに
この記事は、TypeScriptのコンパイル時にエラーが出てしまった人に向けて、その解決策の一つとして紹介します。触りたてであやふやな人でもわかるように書いていきます。

# TypeScriptとは
TypeScriptは、JavaScriptの代替となるべくマイクロソフトによって開発されたオープンソースのプログラミング言語です。TypeScriptの最大の特徴は、静的型付けが導入されていることです。JavaScriptは動的型付けの言語で、変数にどのようなデータ型が入るかを明示的に指定しませんが、TypeScriptでは型を指定することができます。これによって、コードを書いている時点でエラーを防ぐことができ、安全性、可読性の向上の面で使われています。

:::note info
TypeScriptの環境構築については、こちらの@ochiochi様の
[TypeScriptチュートリアル -環境構築編-](https://qiita.com/ochiochi/items/efdaa0ae7d8c972c8103)に詳しく書かれています。
:::

https://qiita.com/ochiochi/items/efdaa0ae7d8c972c8103

# コンパイルエラーの例
TypeScriptのコンパイルエラーは、主に型に関するエラーや構文に関連するものが多いです。いくつかの典型的なコンパイルエラーの例を挙げて、それぞれのエラーがなぜ発生するのかを説明します。
### 1.型の不一致エラー
```Example.ts
let age: number = "30";  
// エラー: 型 'string' を型 'number' に割り当てることはできません
```
ageという変数はnumber型として宣言されていますが、"30"という文字列を代入しようとしています。このように、型が一致しない場合はコンパイルエラーが発生します。
```Example.ts
let age: number = 30;  
```
こちらが、修正されたコードとなります。
### 2.プロパティの存在確認エラー
```Example.ts
interface Person {
  name: string;
  age: number;
}

let person: Person = { name: "John" };  
// エラー: プロパティ 'age' は型 'Person' に必須ですが、'{ name: string; }' に存在しません
```
Personインターフェースにはnameとageの両方が必須のプロパティとして定義されています。しかし、personオブジェクトにはnameプロパティしか含まれていないため、ageが欠けていることでエラーが発生しています。
```Example.ts
interface Person {
  name: string;
  age: number;
}

let person: Person = { name: "John",age: 30};  
```
こちらが、修正されたコードとなります。
### 3.型推論に基づくエラー
```Example.ts
let count = 10;  // TypeScriptはこれをnumberと推論
count = "twenty";  // エラー: 型 'string' を型 'number' に割り当てることはできません
```
TypeScriptはcount変数をnumber型として推論しています。しかし、その後に"twenty"という文字列を代入しようとしたため、型の不一致によるエラーが発生します。
```Example.ts
let count = 10; 
count = 20;  
```
こちらが、修正されたコードとなります。
### 4.数のパラメータ型エラー
```Example.ts
function greet(name: string): void {
  console.log(`Hello, ${name}!`);
}

greet(42);  
// エラー: 型 'number' の引数を型 'string' のパラメータに割り当てることはできません
```
greet関数の引数nameはstring型として定義されていますが、42というnumber型の値を渡しているためエラーが発生しています。
```Example.ts
function greet(name: string): void {
  console.log(`Hello, ${name}!`);
}

greet("John");  
```
こちらが、修正されたコードとなります。
### 5. 未定義のプロパティへのアクセス
```Example.ts
let user: { name: string; age?: number } = { name: "Alice" };

console.log(user.age.toFixed(2));
// エラー: 型 'undefined' かもしれないオブジェクトのプロパティ 'toFixed' を呼び出すことはできません
```
ageはオプショナルプロパティ（age?: number）として定義されています。そのため、ageがundefinedの可能性があり、その状態でtoFixedメソッドを呼び出そうとするとエラーになります。TypeScriptはこのような潜在的なバグを防ぐため、オプショナルプロパティには適切な存在確認が必要です。
```Example.ts
let user: { name: string; age?: number } = { name: "Alice" };

if (user.age !== undefined) {
  console.log(user.age.toFixed(2));
}
```
こちらが、修正されたコードとなります。
### 6.関数の戻り値型エラー
```Example.ts
function getNumber(): number {
  return "Hello";  // エラー: 型 'string' を型 'number' に割り当てることはできません
}
```
getNumber関数はnumber型を返すべきと宣言されていますが、実際には"Hello"という文字列を返そうとしています。この型の不一致によりエラーが発生します。
```Example.ts
function getNumber(): string {
  return "Hello"; 
}
```
こちらが、修正されたコードとなります。
### 7. クラスのプロパティ初期化エラー
```Example.ts
class Car {
  model: string;
  year: number = 2020;
}

let myCar = new Car();
console.log(myCar.model);  // エラー: 'model' の値は使用される前に割り当てられていません。
```
TypeScriptはクラスのプロパティが必ず初期化されることを期待しますが、modelプロパティは初期化されていないためエラーが発生しています。これを解決するには、プロパティに初期値を与えるか、コンストラクタ内で初期化する必要があります。
```Example.ts
class Car {
  model: string = "Unknown";
  year: number = 2020;
}

let myCar = new Car();
console.log(myCar.model);
```
またはコンストラクタ内で、
```Example.ts
class Car {
  model: string;
  year: number = 2020;

  constructor(model: string) {
    this.model = model;
  }
}

let myCar = new Car();
console.log(myCar.model);
```
することによって、修正することができます。
### 8. 範囲外の配列アクセスエラー（厳密なチェックモード時）
```Example.ts
let numbers: number[] = [1, 2, 3];
console.log(numbers[5].toFixed(2)); 
// エラー: 'undefined' かもしれないオブジェクトのプロパティ 'toFixed' を呼び出すことはできません
```
配列のインデックス5には要素が存在しないため、numbers[5]はundefinedです。undefinedに対してtoFixedを呼び出そうとするとエラーになります。範囲外のアクセスは実行時エラーを引き起こす可能性があるため、TypeScriptはこれを防ぎます。
```Example.ts
let numbers: number[] = [1, 2, 3];
console.log(numbers[5]?.toFixed(2));
```
TypeScriptのオプショナルチェイニング（?.）を使って、存在しない場合に自動的に undefined を返すやり方を使用し、修正することができます。
# まとめ
TypeScriptのコンパイル時に発生するであろうエラーとその対処法について、出来るだけたくさん書きました。私自身も、全然できない初学者であるため、間違っている部分やカバーしきれないエラーがあるかもしれません。これらがあなたの助けになれば幸いです。良いTypeScriptライフをお過ごしください！