TypeScriptまとめ

## 変数

```typescript:構文
let name: type [= initial]
```

```typescript:例
let age: number = 30;
```

```typescript:データ型
// boolean型
let flag: boolean = false;

// number型
let age: number = 30;

// string型
let member: string = '山田太郎'

// string型（テンプレート文字列）
let message = `私の
名前は${member}です`;

// 配列型
let pet: string[] = ['犬', '猫', 'ハムスター'];
console.log(pet[2]);                  // ハムスター

// オブジェクト型（連想配列）：インデックスシグニチャ
let duet: { [index: string]: string; } =
  { first: '山田', second: '鈴木' };
console.log(duet['first']);           // 山田

// オブジェクト型（interfaceで切り出し）
interface MyMap { [index: string]: string; }
let duet: MyMap = { first: '山田', second: '鈴木' };

// タプル型
let score: [number, string] = [100, 'great'];
console.log(score[0]);                // 100

// enum型（列挙体）
enum Color { Red, Green, Blue };
let red: Color = Color.Red;
console.log(red);                     // 0
console.log(Color[red]);              // Red
```

## 定数

```typescript:構文
const name: type = value
```

```typescript:例
const PI: number = 3.14;
```

## 型アサーション（型キャスト）

```typescript:構文
<type> variable
variable as type
```

```typescript:例
// 数値をany型にキャスト
<any>108
108 as any
```

## 関数

```typescript:構文
function name(arg: type, ...): r_type {
  ...body...
}
```

```typescript:例
// 引数/戻り値なし
function great(): void {
  console.log('Hello');
}

// 引数/戻り値あり
function add(x: number, y: number): number {
  return x + y;
}

// 匿名関数
let add = function (x: number, y: number): number {
  return x + y;
}

// 省略可能な引数
function showCost(price: number, discount?: number) {
  if (discount) {
    console.log(`価格：${price - discount}円`);
  } else {
    console.log(`価格：${price}円`);
  }
}

// 引数のデフォルト値
function showCost(price: number, discount: number = 0) {
  console.log(`価格：${price - discount}円`);
}

// 可変長引数
function sum(...values: number[]): number {
  let result: number = 0;
  for (let i: number = 0; i < values.length; i++) {
    result += values[i];
  }
  return result;
}
console.log(sum(100, 200, 300));         // 600
```

## アロー関数

```typescript:構文
(arg: type, ...): r_type => {
  ...body...
}
```

```typescript:例
let add = (x: number, y: number): number => {
  return x + y;
}

// より簡易的に書ける
let add = (x: number, y: number): number => x + y;
// さらに簡易的に
let circle = radius => radius * radius / Math.PI;
let hello = () => console.log('Hello');
```

**＃thisが固定される**

## 関数のオーバーロード

```typescript:構文
function name(arg: type, ...): r_type;
function name(arg: type, ...): r_type;
...
function name(arg: type, ...): r_type {
  ...body...
}
```

```typescript:例
function search(str: string, start: number): string;
function search(str: string, start: string): string;
function search(str: string, start: any): string {
  if (typeof start === 'number') {
    return str.substring(start);
  } else {
    return str.substring(str.indexOf(start));
  }
}
let msg = 'いろはにほへとちりぬる';
console.log(search(msg, 3));                // にほへとちりぬる
console.log(search(msg, 'と'));              // とちりぬる
```
## 共用型

```typescript:構文
variable: type1 | type2
```

```typescript:例
function search(str: string, start: number | string): string {
  if (typeof start === 'number') {
    return str.substring(start);
  } else {
    return str.substring(str.indexOf(start));
  }
}
```

## クラス

```typescript:構文
class name {
  modifier variable: p_type;

  modifier constructor(modifier arg: a_type, ...) { ...c_body... }

  modifier method(arg: a_type, ...): r_type { ...m_body... }
}
```

```typescript:例
class Dog {
  constructor(private category: string, private weight: number) {}

  public toString(): string {
    return this.category + ':' + this.weight + 'Kg';
  }
}
let mame = new Dog('豆柴', 8);
console.log(mame.toString());             // 豆柴:8Kg
```

```typescript:静的メンバー
class FigureUtil {
  static PI = 3.14;

  static circle(radius: number): number {
    return radius * radius * this.PI;
  }
}
console.log(FigureUtil.PI);              // 3.14
console.log(FigureUtil.circle(2));       // 12.56
```

## get/setアクセサー

```typescript:構文
get name(); type { ... }
set name(value: type) { ... }
```

```typescript:例
class Dog {
  private _weight: number;

  get weight(): number {
    return this._weight;
  }

  set weight(value: number) {
    if (value < 0) {
      throw new Error('weightプロパティは正数で指定してください');
    }
    this._weight = value;
  }
}
let poodle = new Dog();
poodle.weight = 3
console.log(poodle.weight);        // 3
```

## 継承

```typescript:構文
class name extends parent {
  ...body...
}
```

```typescript:例
class Dog {
  constructor(protected category: string, protected weight: number) {}

  toString(): string {
    return this.category + ':' + this.weight + 'Kg';
  }
}
class UltraDog extends Dog {
  toString(): string {
    return 'スーパー' + super.toString();
  }
}
let dober = new UltraDog('ドーベルマン', 35);
console.log(dober.toString());               // スーパードーベルマン:35Kg
```

## インターフェース

```typescript:構文
interface name extends s_name {
  ...body...
}
```

```typescript:例
interface Pet {
  name: string;
  call(): void;
}
class Dog implements Pet {
  name: string;
  call(): void {
    console.log(this.name + 'ちゃん！');
  }
}
let pochi = new Dog();
pochi.name = 'ポチ';
pochi.call();                       // ポチちゃん
```

```typescript:型注釈
interface Member {
  name: string;
  greet(): void;
}
let mem: Member = {
  name: '山田太郎'
  greet() {
    console.log('こんにちは、' + this.name);
  }
}
mem.greet();

interface AddFunc {
  (a: number, b: number): number;
}
let add: AddFunc = function (x: number, y: number): number {
  return x + y;
}
```

## ジェネリック

```typescript:構文
class name<T> {
  ...body...
}
```

```typescript:例
class GenericClass<T> {
  data: T;
  getData(): T {
    return this.data;
  }
}
let gen = new GenericClass<number>();
gen.data = 108;
console.log(gen.getData());            // 108
```