TypeScript基本入門メモ

#はじめに

自分用のメモです。
誤字脱字があるかもしれません。

#TypeScriptの型
###型のしくみ

```TypeScript
//配列型
var keywords: string[] = ["email", "name", "body"];

//文字列も数値も配列に入れたい場合
var key: (string | number)[] = ["email", "name", "body", 0, 12];

//タプル型(型を指定する)
var payment: [number, string, number] = [1, "apple", 3];

//オブジェクト型
var object: { [key: string]: string } = {
  name: "mikkey",
  id: "test"
};
var post: object = [{ id: 12, content: "les missek" }];

//共用型(Union型)
var sample: string | number | boolean;
sample = "kokugo";
sample = 290;
sample = true;

//enum型（定数をグルーピングする型）
enum KeyCode {
  Backspace = 8,
  Tab = 9,
  Enter = 13
}

console.log(KeyCode.Backspace);

enum Character {
  Bob, //0
  Dad, //1
  Mon //2
}

console.log(Character.Bob);

//any型(使うとTypeScriptの良さが消える)
var something: any = "foo";
something = 100;
something = true;
something = { id: 1 };

//null, undefind型
var el: Element | null = document.querySelector('#app');
var foo : undefined = undefined;


//型推論
var unknown = 'string';
unknown = 12 //エラーになる

```

###変数のしくみ


```TypeScript
//varとletの違い1「ブロックスコープの影響範囲に違いがある」

for(var i = 0; i < 5; i++){
  console.log(i);
}
console.log(i);

>>0
>>1
>>2
>>3
>>4
>>5


for(let j =0; j < 5; j++){
  console.log(j);
}
console.log(j);//Error: j is not definedになる

//varとletの違い２「関数ブロック内の巻き上げ」

var hoge = 'hoge';

function logHoge(){
  //暗黙的に関数内で定義される
  console.log(hoge);
  //予約された変数になる
  var hoge = 'new hoge!';
  console.log(hoge)
}

logHoge();
>>undefined
>>new hoge!
```
###定数のしくみ

```TypeScript
//定数（一度入れたら変更できないデータの箱）
const currentYear: number = 2021;
currentYear = 2022;//エラーになる

```
###テンプレート文字列

```TypeScript
//${}を使用できる
let template1 = `This is Template strngs`;

let name = "hide";

//改行を保持できる
let template2 = `

hello, TypeScript.

Tanks. ${name}

`;
console.log(template2);

```
###スプレッド演算子
・複製や連結が簡単に行える

```TypeScript
let categories = ["post", "news", "into"];

//複製（新しく生成される）
let copyCat = [...categories];
console.log(copyCat); //["post", "news", "into"]

//連結（前）
let pushCat = ['other', ...categories];
console.log(pushCat); //["other", "post", "news", "into"]
//連結（後）
let unshiftCat = [...categories, 'other'];
console.log(unshiftCat); //["post", "news", "into", "other"]

//途中に挿入
let insertCat = ['mike', ...categories, 'kuro'];
console.log(insertCat); //["mike", "post", "news", "into", "kuro"]

//２つの配列をマージ
let margeCat = [...categories,...insertCat]
console.log(margeCat); //["post", "news", "into", "mike", "post", "news", "into", "kuro"]

//オブジェクト
let post= { id: 1, 
            content: 'test',
            created: '2021'
          }

let copyObj = { ...post};
console.log(copyObj); //{id: 1, content: "test", created: "2021"}

//既存のオブジェクトにデータを追加したり上書きしたりできる
let pushObj = { ...post, created: '2030'};
console.log(pushObj); //{id: 1, content: "test", created: "2030"}

//結合できる(インデックス値がキーとなってバリューが設定される)
let mergeObj = {...post, ...pushObj}
```
###分割代入
・配列やオブジェクトでは任意の値を取り出して新しい変数にセットできる仕組み

```TypeScript
let categories = ['post', 'news', 'info', 'other'];

//配列の場合は定義されたインデックスの順に取り出す
let [a, b] = categories;
console.log(a, b); //post news

//初期値を設定することもできる
let[a = 9, b = 7] = [1];
console.log(a, b);//17

//オブジェクトの場合
let post = { id: 1, content: "dummy", created: "2021" };

//変数名を変更する
const {id, content: body} = post;
console.log(id, body);//1dummy

```

###関数のしくみ
```TypeScript
//関数の返り値で値がない場合void(省略してもよい)
function greed(name: string): void {
  console.log(`Hello World! ${name}`);
}

greed("anglara"); //Hello World! anglara

//初期値を設定できる
function greed(name: string = "Taro") {
  console.log(`Hello World! ${name}`);
}

greed(); //Hello World! Taro

//可変長引数(引数の数が決まっていない)
function sum(...valuse: number[]): number{
  //スプレッド演算子を使って配列に入れる
  return valuse.reduce(function(prev, current){
    return prev + current;
  });

}
console.log(sum(1, 3, 4, 9));//17
```
###アロー関数
・より短く記述できる、通常のfunction式の代替構文。
・（） => { }

```TypeScript
let add = (x1: number, x2: number): number => {
  return x1 + x2;
};
console.log(add(1, 3));//4

//thisの扱いが違う
document.getElementById('button1').addEventListener('click', function(){
  console.log(this);//<button></button>
});

//アロー関数は関数が定義された場所のthisを参照する
document.getElementById('button1').addEventListener('click', () => {
  console.log(this);//window
});

```
###クラスのしくみ
プロパティやメソッドを定義する順番
①プロパティ
②コンストラクタやクラスのメソッド

```TypeScript

class クラス名 {

  プロパティ = 'プロパティ1';

  constructor() {
    // 初期化関数
    this.プロパティ = 'プロパティ';
  }

  メソッド1() {
    console.log('テスト');
    this.プロパティ = 'プロパティ3';
  }
}
const インスタンス = new クラス名(); // インスタンス化
インスタンス.プロパティ = 'プロパティ2';
インスタンス.メソッド1();
```
###アクセス修飾子
・public・・・どこからでもアクセスできる
・protected・・・自身のクラスとその派生クラスの中でアクセスできる
・private・・・そのクラスの中でのみアクセス可能

###アクセサメソッド
・プロパティ名と同じアクセサメソッドは定義できない

```TypeScript
//クラス
class Animal {

  age: number = 10;
  private _legs = 3;

  constructor(public isCry: boolean) {}

  cry(): void {
    if (this.cry) {
      // alert(`age: ${this.age}`);
    }
  }
//アクセサメソッド（getter, setter)
  
  //値の設定
  get legs(){
    //検証することで安全なプロパティアクセスができる
    if(this._legs > 2){
      return this._legs;
    }
  }
  //値の取得
  set legs(value: number){
    if(value > 1){
      this._legs = value;
    }
  }
}

let dog = new Animal(true);
dog.cry();
console.log(dog.legs);//3

```

###クラスの継承
継承する前提で親クラスを作成する際には親クラスの変更先が変更を与える可能性が高いので注意が必要

```TypeScript
//クラス
class Animal {
  age: number = 10;

  constructor(public isCry: boolean){ 
    this.age = 2; 
  }

  cry(): void{
    if(this.cry){
      alert(`age: ${this.age}`)
    }
  }
}

//クラスの継承
class Dog extends Animal{

　//省略することもできる 
  constructor(public isCry: boolean){
    //記述がないと初期化されない
    super(isCry);
    this.age = 10;
  }

  cry(): void{
    if(this.cry){
      alert(`age: ${this.age}`)
    }
    console.log('Dog is cry!');
    super.cry;
  }

}

let dog = new Dog(true);
dog.cry();

```
###インターフェイスのしくみ
クラス定義やデータ定義を統一することが目的

```TypeScript
//インターフェース
interface Animal {
  name: string;
  legs: number;
  isCry: boolean;
  cry(): void;
}

//インターフェースの継承
interface SuperAnimal extends Animal{
  //定義を追加することもできる
  canRun: boolean;
}

//定義していないとコンパイルエラーになる
class Dog implements SuperAnimal {
  name: string = 'cherry';
  legs: number = 4;
  isCry:boolean = true;
  canRun: boolean = true;

  cry(): void{
    if(this.isCry){
      console.log('Bow Bow!');
    }
  }
}
//オブジェクトにもインターフェースを適応できる
let Dog : Animal = {
  name: 'cherry',
  legs: 4,
  isCry: true,
  cry: function(){
    console.log('Bo! bo!');
  } 
};

let cherry = new Dog;
cherry.cry();

```
###ジェネリックのしくみ
クラスの外側から内部の型を指定できる
汎用的なクラスやメソッドの内部に型を対応させることができる

```TypeScript

class Store<T> { // T(Type), U , V , T1, T2, T3
  data: T; // number
  getStore(): T {
    return this.data;
  }
}

let stringData = new Store<number>();
let booleanData = new Store<boolean>();

function hello<T>(keyword: T) {
  console.log(`Log: ${keyword}.`);
}
hello<string>('Hello, Takumi');
hello<number>(100);

class Component<T, U> {
  name: T;
  created: U;
}
let component = new Component<string, number>();

```
#参考
【2021年最新版】はじめてのAngular入門 実践シングルページアプリケーション（SPA）開発
超TypeScript入門 完全パック(2021)