基本的なTypeScriptの文法

# TypeScriptとは
TypeScriptは、JavaScriptのスーパーセットとして設計されたプログラミング言語です。マイクロソフトによって開発され、静的型付けを特徴としています。これにより、変数や関数の型を明示的に宣言することができ、開発時のエラーを早期に検出することが可能となります。TypeScriptは、JavaScriptのすべての機能を含みつつ、型安全性と大規模アプリケーションの開発を容易にするための追加機能を提供します。これにより、コードの品質と保守性が向上し、開発者の生産性も高まります。

※スーパーセット・・・元の言語との互換性を保ちつつ、元の言語を拡張して作った言語のことを指します。TypeScriptは、JavaScriptとの互換性を保ちつつ、JavaScriptを拡張して作った言語です。

## コンパイル
TypeScriptは、ブラウザやNode.jsで直接実行することができないため、実行する前にJavaScriptに変換する必要があります。この変換のプロセスを**コンパイル**と言います。
コンパイルの際、TypeScriptコードはJavaScriptコードに変換され、型チェックやその他の検査も同時に行われます。

## 型注釈
変数などに対して明示的に型をつけることを型注釈と言います。
```typescript
const message: string = "Hello World";

function add(x: number, y: number): number {
	return x + y;
}
```

## 型推論
一方で型宣言を省略し、代入された値から型を推測してくれることを型推論と言います。
```typescript
const message = "Hello World";

function add(x, y) {
	return x + y;
}
```


# 基本的な文法

## プリミティブ型
- boolean：真偽値
- number：数値
- string：文字列
- bigint：大きな整数
- symbol：一意の値を示す
- undefind：値が定義されていない状態を示す
- null：値が存在しない状態を示す
```typescript
const isReturn: boolean = false;
const age: number = 10;
const name: string = "山田太郎";
const bigNumber: bigint = 100n;
const uniqueNumber: symbol = Symbol("unique");
const notNumber: undefind = undefind;
const empty: null = null;
```

## 特殊な型
- **any**：何でも代入できる型です。型が不明な場合や、動的に型が決まる値を扱うときに使用します。ただし、any型を使うと型チェックが無効化され、型の安全性が低下するため、必要な場合に限定して使うことが推奨されています
```typescript
let value: any;
value = 123;
value = "Hello";
value = true;
```

- **unknown**：any型と似て、何でも代入できる型です。しかし、unknown型に対しては、具体的な型が判明するまで操作が制限されます。これにより、型の安全性が保たれます
```typescript
let value: unknown;

value = 42;
value = "Hello, world!";
value = { name: "Alice" };

// 直接の操作はできない（コンパイルエラーになる）
value.foo();          // コンパイルエラー
value.toUpperCase();  // コンパイルエラー

// 型チェック後に操作可能
if (typeof value === "string") {
  console.log(value.toUpperCase());  // OK
}

if (typeof value === "object" && value !== null) {
  console.log((value as { name: string }).name);  // OK
}

```

- **void**：値が存在しないことを示す型です。主に、何も返さない関数の戻り値として使用されます
```typescript
function logMessage(message: string): void {
  console.log(message);
}
```

- **never**：決して何も返さないことを示す型です。エラーを投げる関数や、無限ループの関数の戻り値として使用されます
```typescript
function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}
```

- **literal**：指定した型の特定の値しか代入できない型です。リテラル型を使うと、特定の文字列や数値などの値を限定することができます
```typescript
let direction: "up" | "down";
direction = "up";  // OK
direction = "left"; // エラー
```

- **object**：オブジェクト型で、基本的に `{}` を使って型アノテーションを行います。プロパティの型を明示的に指定することで、オブジェクトの構造を定義できます
```typescript
let person: { name: string; age: number };
person = { name: "John", age: 30 };
```

- **array**：配列の型定義には、`T[]` 構文と `Array<T>` 構文の2つがあります。どちらも同じ意味ですが、状況に応じて使い分けられます
```typescript
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
```

- **tuple**：要素数と型が固定された配列です。要素ごとに異なる型を指定できるため、決まった構造のデータを扱う場合に有効です
```typescript
let tuple: [string, number];
tuple = ["hello", 42];  // OK
tuple = [42, "hello"];  // エラー
```

- **union**：``|`` を利用して複数の型を許容する変数を作成できます。これにより、変数が複数の型を持つことができます
```typescript
let id: number | string;
id = 123;       // OK
id = "ABC123";  // OK
```

- **enum**：関連する一連の数値または文字列値の集まりを定義するための型です。複数の選択肢がある値を管理する場合に便利です
```typescript
enum Direction {
  Up = 1,
  Down,
  Left,
  Right
}

let dir: Direction = Direction.Up;
```

## 型エイリアス
型エイリアスは、TypeScriptで複雑な型に対してわかりやすい名前をつけるために使用します。これにより、再利用可能なカスタム型を定義でき、コードの可読性と保守性が向上します。
```typescript
type UserID = string | number;

let user1: UserID = "abc123";
let user2: UserID = 987654321;

type Point = {
  x: number;
  y: number;
};

let p: Point = { x: 10, y: 20 };
```

## インターフェース
インターフェースは、オブジェクトの構造を定義するために使用します。型エイリアスと似ていますが、インターフェースはプロパティやメソッドの設計図を定義するのに特化しており、オブジェクト指向プログラミングでよく使われます。また、インターフェースは継承が可能で、複数のインターフェースを組み合わせることもできます。
```typescript
interface Person {
  name: string;
  age: number;
  greet(): void;
}

let user: Person = {
  name: "Alice",
  age: 25,
  greet() {
    console.log("Hello, " + this.name);
  }
};

user.greet(); // "Hello, Alice"
```

## オプショナルプロパティ
オプショナルプロパティは、インターフェースや型エイリアスで定義されるプロパティが、必須ではないことを示すために使用します。プロパティ名の後に ? を付けることで、そのプロパティがオプションであることを明示します。これにより、プロパティが存在しないオブジェクトを許容することができます。
```typescript
interface Product {
  name: string;
  price: number;
  description?: string; // オプショナルプロパティ
}

let item1: Product = {
  name: "Laptop",
  price: 1500
};

let item2: Product = {
  name: "Phone",
  price: 800,
  description: "Latest model"
};
```