便利なTypeScriptの書き方4選

#はじめに
今年から本格的にTypeScriptを書き始めたので、個人的に便利だなと思った便利記法4つを選んでまとめてみました。

※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。

#1/ 変数末尾に 「 ! 」 をつけることで初期化チェックを割愛
## きっかけ
継承がうまくいかないと思った時に、先輩からレビューいただき学びがありました。


## うまくいかなかったこと

エラーにはなっていないが、冗長的なクラス文

```typescript
class Personality {
  personality: PersonalityEntity;
  constructor(personality: Personality, channel: Channel) {
    this.personality = {
      id : personality.id,
      name : personality.name, 
      .....省略....
      age : personality.age
         };
       }
     }

//↑を継承
class PersonalityDetail extends Hoge {
  personality:PersonalityDetailEntity
  include:hoge;
  constructor(personality: Personality ,channel: Channel, fugas : Fuga) {
    super(personality) // ---- ①
    this.personality = {
      id:personality.id, 
      name:personality.name, 
       .....省略....
      age : personality.age,
      gender : personality.gender(継承先で新しく追加したプロパティ)
        }
    this.include = fugas.map(fuga => { 
     .....省略.... 
     });
  }
```

内容は違うけど、ざっくりこんな感じで書いていて、

構文には間違っていないので動くけど、
継承してる割にはPersonalityDetailのconstructorのthisの中身が同じで冗長的なふうに感じ、リファクタリングできないかなと感じていた。

## よくやってしまうミス

### 継承をしない

現状、上記のコードだと**super**で継承しているPersonalityクラスのpersonalityプロパティが生成された後（上記①）に、継承先で新しく追加したプロパティ（ここではgender）と一緒に**上書き**してしまっているような状態で、二重の初期化がかかり、**superが意味のない処理になっています**。

そこで、**継承をせずに**下記のように修正。

```tsx
class Personality {
  personality: PersonalityEntity;
  constructor(personality: Personality, channel: Channel) {
    this.personality = {
      id : personality.id,
      name : personality.name, 
       .....省略....
      age : personality.age
      };
    }
 }

class PersonalityDetail { //継承しない
  personality : PersonalityDetailEntity
  include : hoge;
  constructor(personality: Personality ,channel: Channel, fugas : Fuga) {
    this.personality = { 
      id : personality.id, 
      name : personality.name, 
      .....省略....
      age : personality.age,
      gender : personality.gender 
     }
     this.include = fugas.map(fuga => { 
      .....省略.... 
      });
    }
 }
```

上記のように**継承しないで PersonalityDetailを1から新しく作り、**親であったPerosonalityのクラスは全く関係ないよと宣言したパターン。

これだと、上下のクラスで**全く依存関係はない**ので、初期化はthis以降の1回だけで、上書きは起きない。が、しかし

### 継承をしないと

上記の場合だと、PersonalityDetailはPersonalityの**子クラス**ではあるため、**もし継承を外したら、親クラスのPersonalityの作り方が変わった場合に、子クラスのPersonalityDetailもその都度修正**しなくちゃいけなくなるのでエラーにならなくても**望ましくない。**

## 解決方法

### スプレッド構文で親クラスのコンストラクタ内のプロパティを継承

```tsx
class PersonalityDetail extends Hoge { //継承する
  personalit : PersonalityDetailEntity
  include : hoge;
  constructor(personality: Personality ,channel: Channel, fugas : Fuga) {
    super(personality,channel) 
    this.personality = {
       ...this.feed, //スプレッド構文でpersonalityプロパティを継承
       gender : personality.gender (継承先で新しく追加したプロパティ
        }
    this.include = fugas.map(fuga => { 
     .....省略.... 
     })
   }
```

このように、**スプレッド構文「...」**で親クラスのコンストラクタ内で定義したプロパティを**丸っと（←ここを良い感じにしてくれる）**継承します。

スプレッド構文を使うことで、冗長さはなくなり見通しの良いコードになりました。

**スプレッド構文「...」ついては別途まとめます。**


しかしこれだけだと、this.personalityを使おうとするとプロパティ 'personality' は割り当てられる前に使用されています。

と**「コンストラクタで初期化できないエラー」**がでるんで、**無視させる必要があります。**

今日のテーマはここからです。笑

そこで、

```typescript
class PersonalityDetail extends Hoge {
  personality! : PersonalityDetailEntity
  include : hoge;
  constructor(personality: Personality ,channel: Channel, fugas : Fuga) {
    super(personality,channel) 
    this.personality = {
      ...this.field
      gender : personality.gender （継承先で新しく追加したプロパティ）
       }
    this.include = fugas.map(fuga => { 
     .....省略.... 
    })
  }
```

と、Personalityという**変数末尾に「 ! 」 をつけることで初期化チェックを割愛（無視）できます。**

https://qiita.com/vvakame/items/3a1e628e53a5dd99dfe0#%E5%A4%89%E6%95%B0%E6%9C%AB%E5%B0%BE%E3%81%AB--%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%A7%E5%88%9D%E6%9C%9F%E5%8C%96%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%82%92%E5%89%B2%E6%84%9B%E3%81%A7%E3%81%8D%E3%82%8B

↑記事によると**「newした後に他のメソッドが呼ばれるまでにプロパティが初期化できる」**ということがわかる場合があり、
そういう時のための抜け穴という訳らしい。

これで継承もうまくいった！

今回はあくまで例文でしたが、最終的にはこんな感じ。

```typescript
class Personality {
  personality : PersonalityEntity;
  constructor(personality: Personality, channel: Channel) {
  this.personality = {
    id : personality.id,
    name : personality.name, 
    .....省略....
    age : personality.age
    };
  }
}

class PersonalityDetail extends Hoge {
  personality! : PersonalityDetailEntity
  include : hoge[];
  constructor(personality: Personality ,channel: Channel, fugas : Fuga) {
    super(personality,channel) 
    this.personality = {
      ...this.field
      gender : personality.gender (継承先で新しく追加したプロパティ)
        }
    this.include = fugas.map(fuga => { 
      .....省略.... 
    })
 }
```

## 【まとめ】 変数末尾に 「 ! 」 をつける

- super(継承したプロパティ)とthis.継承したプロパティで同じ継承したプロパティをセットしていたら、
せっかくsuperで親から継承している処理に対し、thisで上書きしていることになり2**重の初期化**が掛かってしまうことになる。
- **スプレッド構文「...」**で親クラスのコンストラクタ内で定義したプロパティを丸っと（←ここを良い感じにしてくれる）継承できる。
- **変数末尾に「 ! 」 をつけることで初期化を割愛（無視）できる**。

# 2/ スプレッド構文の便利な使い方

## **スプレッド構文とは**

### **記述方法**

```terminal
...//ピリオド3つ
```

です。なんとシンプル。

## **意味**

JavaScriptやTypeScriptにおいて

:::note info
💡 オブジェクトのプロパティや配列の要素を引き継いで、展開できる
:::


になります。

## **具体例**

こんな感じで使う

```tsx
const person = { 
  age: 34, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa', 
}; 

console.log(person); 

const actress = {
  ...person, // ここでスプレッド構文を使う 
  area: 'Tokyo', 
  title: 'Beauty Actress', 
}; 

console.log(actress); 
// arr2 = { foo: 1, bar: 2 }
```

です

実行結果

```typescript
{ 
  age: 34, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa' 
} 
{ 
  age: 34, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa' ,
  area: 'Tokyo', 
  title: 'Beauty Actress' 
}
```

です。

内容はさておき、上のコードではまず person という変数で、
名前 (firstName, lastName) や年齢 (age) などのプロパティを設定したオブジェクトを作っています。

次に person の内容を**スプレッド構文で引き継いで**、
さらにエリア (area) とか役職 (title) などのプロパティを追加設定して、actress オブジェクトを作成しています。

このように、**元のプロパティの内容を全て引き継いで、展開することを可能にするのが`スプレッド構文`。**

## **値を全部引き継いでから書き換える**

スプレッド構文で値を引き継いだ後に、**データを更新（上書き）することもできます**。

例えば、上の例で、`person`の内容の中で、`age`だけ書き換えて、

子のオブジェクトに引き継ぐには次のようにかけます。

```tsx
const person = { 
  age: 34, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa' 
};
 
console.log(person); 

const actress = { 
  ...person, 
  age: 29, //34から変更  
  area: 'Tokyo', 
  title: 'Beauty Actress'
}; 

console.log(actress);
```

です。

実行結果

```tsx
{ 
  age: 29, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa' 
} 
{ 
  age: 34, 
  firstName: 'Keiko', 
  lastName: 'Kitagawa' ,
  area: 'Tokyo', 
  title: 'Beauty Actress' 
}
```

## **配列の場合**

配列も引き継げます。

```tsx
const foo = [1, 2]; // 配列のクローン  
const bar = [...foo]; // 実行結果=> [1, 2]  // 要素を追加して新しい配列を生成
const baz = [...foo, 3, 4]; // 実行結果 => [1, 2, 3, 4]  // 配列をマージ 
const hoge = [...foo, ...bar]; // 実行結果 => [1, 2, 1, 2]
```

`Array.prototype.concat()`と同じようなことが簡潔にかけます。

## 配列を分割する

スプレッド構文の組み合わせで、**配列要素を取り出しつつ、残りを変数に代入すること**も可能。

```tsx
let [a, b, ...other] = [1, 2, 3, 4, 5]; 
console.log(a); // 1  
console.log(b); // 2  
console.log(other); // [3, 4, 5]
```

このように分割代入と組み合わせると配列の分割も簡単。分割代入は別途書きます。

## 【まとめ】 スプレッド構文

- スプレッド構文の記述方法は`...`とピリオド3つ
- オブジェクトのプロパティや配列の要素を引き継いで、展開できる
- スプレッド構文で値を引き継いだ後に、データを更新（上書き）することも可能。
- スプレッド構文と分割代入との組合わせも可能

**参考**

- [JSのスプレッド構文を理解する - Qiita](https://qiita.com/akisx/items/682a4283c13fe336c547)

# 3/ 分割代入とは

初めて見たときは「なんじゃこりゃ」と思ったが今でも覚えてる構文です。


## 分割代入とは

分割代入とは

:::note info
💡 配列とオブジェクトを分解して、要素とプロパティ値を1つ1つの変数に分解するための構文。
:::


言葉だと、わかりずらいので例文。

```tsx
const player = ['大谷翔平' , 26 , 193 , 165 ]
```

この配列の中の4つの値は、それぞれ名前・年齢・身長・球速を表しています。そこで、分かりやすいように名前をつける。

```tsx
const name = player[0]; 
const age  = player[1]; 
const height = player[2]; 
const speed  = player[3];
```

これは間違ってはないけど、手間である。

そこで、分割代入が使える。

```tsx
const name = player[0]; 
const age  = player[1]; 
const height = player[2]; 
const speed  = player[3];`

const player = ['大谷翔平' , 26 , 193 , 165 ] 
const [name, age, height, speed] = player; 

console.log(name) // ['大谷翔平'] 
console.log(age) // [26] 
console.log(height) // [193] 
console.log(speed) // [165]`
```

### 一部の値だけ使う場合

ちなみにnameとspeedだけ使いたい場合は、

```tsx
const [name , speed] = player;
```

こうも書ける。

上記と同じく一部の値を省略することもできる。

```tsx
const player = ['大谷翔平' , 26 , 193 , 165 ] 
const [, , height, speed] = player; 

console.log(height) // [193] 
console.log(speed) // [165]
```

### スプレッド構文との併用

スプレッド構文を使うと、残りの要素をまとめて拾うことができる。

```tsx
const player = ['大谷翔平' , 26 , 193 , 165 ]
const [name, age, ...other] = player;

console.log(other)
> [ 193 , 165 ]
```

### **オブジェクトを作る場合**

例えば、これをつかって**オブジェクトを作る場合**。

```tsx
const player = ['大谷翔平' , 26 , 193 , 165 ] 
const [, , height, speed] = player; 
const baseballPlayer = { 
  name : name, 
  age : age , 
  hight : hight, 
  speed : speed,
}
```

↑はもっと簡単にかける

```tsx
const player = ['大谷翔平' , 26 , 193 , 165 ]
const [, , height, speed] = player;
const baseballPlayer = { 
  name,
  age ,
  hight,
  speed,
}
```

と、オブジェクトを作成する際、

**オブジェクトのキー名（変数名）と値（value）が同じ場合、値（value）を省略して、変数名だけ記述**

することができます。またこれは別途書きます。

## 実務で配列の分割代入を使用する例

上記は説明するために書いたが、実際の運用コードでは [1, 2] のような**要素が固定された配列はあんまり登場**しない。

では、どんなときに配列の分割代入を使用するメリットがあるのか？

経験上、実務では、**配列の順番に意味がある時** によく使う。

### 例えば

```tsx
const hogeChannel = ....省略....
const hogeChannel = ....省略....
const hogeChannel = ....省略....
const hogePersonality = ....省略....

const [episodes, channel, personality] = 
  await Promise.all([hogeIncludes , hogeChannel , hogePersonality]); 
  return { channel, episodes, personality, };
```

とこんな感じ**関数の引数**として配列の順番を意識して使ったり、上の続きで、

```tsx
async function getAllData(id: string):

....省略....

const [episodes, channel, personality] = 
  await Promise.all([hogeIncludes , hogeChannel , hogePersonality]);
    return { channel, episodes, personality, };
}

async function main(hoge: Request): Promise<Response> { 
  return getAllData(hoge.id) 
    .then(({ channel, episodes, personality }) => { 
      return new Response( channel, episodes, personality); 
})
```

とこんな感じで、

**(Rest)APIのレスポンスを返す際に、今まで定義した変数をまとめてインスタンスを作成し、コンストラクタにつっこむ時**に上手く使ったりする。

## 【まとめ】 分割代入

- 分割代入とは、配列（やオブジェクト）を分解して、要素とプロパティ値を1つ1つの変数に分解するための構文。
- 配列の要素は省略可能。
- 興味のない要素は、「,,,」で変数名を省略することで無視ができる。
- スプレッド構文を使うと、残りの要素をまとめて拾うことができる。
- 配列と同じく、変数宣言と同時にオブジェクトの要素の値が代入できる。
- 経験上、実務では**配列の順番に意味がある時** に**関数の引数や、**APIのレスポンスを返す際に、今まで定義した変数をまとめてインスタンスを作成し、コンストラクタにつっこむ時に分割代入を使う。

**参考**

- [分割代入 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
- [4歳娘「パパ、懐かしいJavaScript書いてるね！」 - Qiita](https://qiita.com/Yametaro/items/70e7878c5ea51788b643)
- [今さら分割代入知らないなんて言えないのでTypeScriptでこっそり勉強する - Qiita](https://qiita.com/ringtail003/items/b4de9278cd507feb2478#%E4%BB%A3%E5%85%A5%E5%85%88%E3%81%AE%E8%A6%81%E7%B4%A0%E6%95%B0%E3%82%88%E3%82%8A%E9%85%8D%E5%88%97%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB%E3%81%AE%E8%A6%81%E7%B4%A0%E6%95%B0%E3%81%8C%E5%B0%91%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88)

# 4/ valueの省略記法
## key:valueの省略

といっても上記がすべて。

ES6(ES2015)にて、オブジェクトのプロパティのキー名と値の変数名が等しい場合、

省略して**変数名だけで記述**することができます。

```tsx
const foo = 1 
const arr = { 
  foo: foo 
} 

// ES6 
const foo = 1 
const arr = {
	foo
} 
// => arr = { foo: 1 } 

const arr2 = { 
  foo,  //foo : foo と key : value = 変数名:値 の構成で書かなくてOK 
  bar : 2 
} 
// arr2 = { foo: 1, bar: 2 }
```

このように、`foo : foo`と`key : value`の構成が同じ場合、

つまり`変数名 : 値`の構成が同じ場合、変数名だけ書いてvalue（値）を省略することができる。

[ECMAScript 6: New Features: Overview and Comparison](http://es6-features.org/#PropertyShorthand)

# 【まとめ】 valueの省略記法

- オブジェクトのプロパティのキー名と値の変数名が等しい場合、
`変数名 : 値`の構成で書かずに、変数名だけ書いてvalue（値）を省略することができる。

**参考**

- [あなたが知らないJavaScriptの便利すぎるショートハンド19選](https://www.webprofessional.jp/shorthand-javascript-techniques/)