【JS / TS】Hooks がわからんのではない、分割代入をわかっていないだけ（複雑な分割代入編）

## 0.はじめに

分割代入の第3段の記事になります。

今回は、オブジェクトと配列の混合の分割代入編の記事となります。

 [オブジェクト編](https://qiita.com/daishiman/items/5acf803f252b82f970fe) 、[配列編](https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf)の記事も見て頂けると、うれしいです。



## 1.この記事を読んだら、できるようになること

:::note info

「分割代入まじわからん」を克服できるようになります

下記の分割代入を理解することができます。

- オブジェクトの分割代入
- 配列の分割代入
- **複雑な分割代入 ← 今回はここ**


:::

下記の分割代入を理解することができるようになります。

```ts:
const {
	nickname: userName = '名無し',
	age = 132,
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage],
			[firstFrontEndFW, ...otherFrontEndFW]
		],
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
		infra
	}
} = user;
```

記事が長くなりそうなので、分割代入の記事を分割して書きます😏  
今回は、**複雑な分割代入編**になります。

## 2.目次

[0. はじめに](https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa#0%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)  
[1. この記事を読んだら、できるようになること](https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa#1%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A0%E3%82%89%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%93%E3%81%A8)  
[2. 目次](https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa#2%E7%9B%AE%E6%AC%A1)  
[3. 環境]()  
[4. 分割代入とは](https://qiita.com/daishiman/items/5acf803f252b82f970fe#3%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5%E3%81%A8%E3%81%AF)  
[5. オブジェクトの分割代入](https://qiita.com/daishiman/items/5acf803f252b82f970fe#5%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)   
[6. 配列の分割代入](https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf#6%E9%85%8D%E5%88%97%E3%81%AE%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)  
**[7. 複雑な分割代入](https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa#7-%E8%A4%87%E9%9B%91%E3%81%AA%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)  ← 今回はここ**  



## 7. 複雑な分割代入

### 7.1. 複雑な分割代入

今まで、[オブジェクト](https://qiita.com/daishiman/items/5acf803f252b82f970fe#4%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)・[配列](https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf#5%E9%85%8D%E5%88%97%E3%81%AE%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)の分割代入を見てきましたが、  
今回は、**複雑な**分割代入を見ていきます。


#### 7.1.1. 使用するオブジェクト

使用するオブジェクトは、下記の通りです。

```ts:
type User = {
	nickname?: string;
	age?: number;
	programmingSkills?: {
		frontEnd?: Array<Array<string | undefined>>;
		backEnd?: Array<Array<string | undefined>>;
		infra?: Array<string | undefined>;
	}
}

const user: User =
	{
		nickname: 'daishi',
		programmingSkills: {
			frontEnd: [
				['JavaScript', 'typescript'],
				['React', 'Next.js', 'Vue', 'Nuxt.js']
			],
			backEnd: [
				['PHP', 'Ruby', 'Java'],
				['Laravel', 'Symfony', 'Ruby on Rails', 'Spring']
			],
			infra: ['AWS', 'Docker', 'Linux'],
		}
	};
```




#### 7.1.2. 分割代入で記述

下記の分割代入で挙動を確認したいと思います。

```ts:
const {
	nickname: userName = '名無し',
	age = 132,
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage], 
			[firstFrontEndFW, ...otherFrontEndFW]
		],
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
		infra
	}
= user;

// 実行
console.log(userName);              // daishi
console.log(age);                   // 132
console.log(firstFrontEndLanguage); // JavaScript
console.log(otherFrontEndLanguage); // ['typescript']
console.log(firstFrontEndFW);       // React
console.log(otherFrontEndFW);       // ['Next.js', 'Vue', 'Nuxt.js']
console.log(firstBackEndLanguage);  // PHP
console.log(otherBackEndLanguage);  // ['Ruby', 'Java']
console.log(firstBackEndFW);        // Laravel
console.log(otherBackEndFW);        // ['Symfony', 'Ruby on Rails', 'Spring']
console.log(infra);                 // ['AWS', 'Docker', 'Linux']
```

実行結果も見ても、  
「うーん？？？・・・・意味わからん？？？？？？」  
ってなりますよね。

なので、今までやってきたように分割代入を使わない方法で記述してみると、  
何をしているか、見えてくると思います。


今までの記事の応用となっているので、  
今までの記事をご覧になってからの方が理解しやすいかもです😎

https://qiita.com/daishiman/items/5acf803f252b82f970fe

https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf


#### 7.1.3. 分割代入を分解する

様々な情報が入っているので、まずは、プロパティ毎に分解します。  

```ts:分割１
const {
	nickname: userName = '名無し',
} = user;
```

```ts:分割２
const {
	age = 132,
} = user;
```

```ts:分割３
const {
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage],
			[firstFrontEndFW, ...otherFrontEndFW]
		],
	}
} = user;
```


```ts:分割４
const {
	programmingSkills: {
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
	}
} = user;
```

```ts:分割５
const {
	programmingSkills: {
		infra,
	}
} = user;
```

分解するだけで、見え方が変わったと思います。

僕は、この分解をやってこなかったため、**「分割代入がまじわからん」** ってなっていました...  

**分割マジ大事ですね！！**

:::note warn

コメント 
- 分割４, ５は、`frontEnd`, `backEnd` を配列よりもオブジェクトでネストした方が、使いやすい思いますが、  
 **配列の中に配列を入れた** サンプルとしたかったので、このような形をとりました。
- 分割４, ５のレスト構文（`...otherFrontEndLanguage` こんなやつ）については、別の記事にまとめる予定なので、説明は省略いたしますm(_ _)m

:::


#### 7.1.4. 分割代入を使用しないで記述

いつものごとく、分割代入を使用せずに記述して確認します。

詳細は、今までの記事にまとめていますので、概要説明となります。

##### 7.1.4.1. 分割１ 

```ts:分割１
// 分割代入で記述
const {
	nickname: userName = '名無し',
} = user;

// 分割代入を使用しないで記述
const userName = user.nickname;

// 実行
console.log(userName); // daishi
```

- `nickname: userName` は、別名の `userName` で定義を示す（詳細は[こちらの記事](https://qiita.com/daishiman/items/5acf803f252b82f970fe#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%A8%E3%81%AF%E5%88%A5%E5%90%8D%E3%81%AE%E5%A4%89%E6%95%B0%E3%81%AB%E3%81%84%E3%82%8C%E3%82%8B)を参照）
-  `userName = '名無し'` は、デフォルト値を定義を示す（詳細は[こちらの記事](https://qiita.com/daishiman/items/5acf803f252b82f970fe#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4)を参照）


##### 7.1.4.2. 分割2

```ts:分割２
// 分割代入で記述
const {
	age = 132,
} = user;

// 分割代入を使用しないで記述
const age = user.age;

// 実行
console.log(age); // 132
```

- `age = 132` （ひみつ）は、デフォルト値を定義を示す（詳細は[こちらの記事](https://qiita.com/daishiman/items/5acf803f252b82f970fe#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4)を参照）
- `age` プロパティには、何も入っていないのでデフォルト値の `132` （ひみつ）が入る


##### 7.1.4.3. 分割3

```ts:分割３
// 分割代入で記述
const {
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage],
			[firstFrontEndFW, ...otherFrontEndFW]
		],
	}
} = user;

// 分割代入を使用しないで記述
const firstFrontEndLanguage  = user.programmingSkills.frontEnd[0][0];
const otherFrontEndLanguage; = ['typescript'] // レスト構文の説明は省略

const firstFrontEndFW        = user.programmingSkills.frontEnd[1][0];
const otherFrontEndFW;       = ['Next.js', 'Vue', 'Nuxt.js'] // レスト構文の説明は省略


// 実行
console.log(firstFrontEndLanguage); // JavaScript
console.log(otherFrontEndLanguage); // ['typescript']

console.log(firstFrontEndFW);       // React
console.log(otherFrontEndFW);       // ['Next.js', 'Vue', 'Nuxt.js']
```

分割4, 5 が最も難しそうに感じますが、オブジェクトの中に配列をネストした分割代入です。（詳細は[こちらの記事](https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf#%E9%85%8D%E5%88%97%E3%81%AE%E4%B8%AD%E3%81%AB%E9%85%8D%E5%88%97%E3%81%8C%E3%83%8D%E3%82%B9%E3%83%88%E3%81%97%E3%81%9F%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)を参照）

※ `otherFrontEndLanguage`, `otherFrontEndFW` レスト構文の説明は省略させていただきますm(_ _)m


##### 7.1.4.4. 分割4


```ts:分割４
// 分割代入で記述
const {
	programmingSkills: {
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
	}
} = user;

// 分割代入を使用しないで記述
const firstBackEndLanguage = user.programmingSkills.backEnd[0][0];
const otherBackEndLanguage = ['Ruby', 'Java'] // レスト構文の説明は省略

const firstBackEndFW       = user.programmingSkills.backEnd[1][0];
const otherBackEndFW;      = ['Symfony', 'Ruby on Rails', 'Spring'] // レスト構文の説明は省略


// 実行
console.log(firstBackEndLanguage); // PHP
console.log(otherBackEndLanguage); // ['Ruby', 'Java']

console.log(firstBackEndFW);       // Laravel
console.log(otherBackEndFW);       // ['Symfony', 'Ruby on Rails', 'Spring']
```

※ `otherBackEndLanguage`, `otherBackEndFW` のレスト構文の説明は省略させていただきますm(_ _)m

##### 7.1.4.5. 分割5

```ts:分割５
// 分割代入で記述
const {
	programmingSkills: {
		infra
	}
} = user;

// 分割代入を使用しないで記述
const infra = user.programmingSkills.infra;

// 実行
console.log(infra); // ['AWS', 'Docker', 'Linux']
```

### 7.2. 変数名の定義で注意すること

左辺の変数名の定義で注意点があります。
僕は、これをやっていまい無駄に時間を使ってしまいました😅

分割4, 5 の変数を

```ts:
const {
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage],
			[firstFrontEndFW, ...otherFrontEndFW]
		],
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
	}
} = user;
```

としましたが、

```ts:
const {
	programmingSkills: {
		frontEnd: [
			[firstLanguage, ...otherLanguage],
			[firstFW, ...otherFW]
		],
		backEnd: [
			[firstLanguage, ...otherLanguage],
			[firstFW, ...otherFW]
		],
	}
} = user;
```

とすると、

:::note alert

コンパイルエラーとなります。

:::


理由は、分割代入を使わずに書いてみるとわかります。

`frontEnd` の `firstLanguage` は、

```ts:
const firstLanguage  = user.programmingSkills.frontEnd[0][0];
```

`backEnd` の `firstLanguage` は、

```ts:
const firstLanguage  = user.programmingSkills.backEnd[0][0];
```

となり、同じ変数に代入することになります。

`const` を使っているのに **再代入** してしまっていたということです。

:::note info

分割代入内には、同じ変数を定義することができません

:::

複雑な分割代入だと見落としがちになるので、注意が必要です。

### 7.3. ここまで理解することができると

```ts:
const {
	nickname: userName,
	programmingSkills: { frontEnd }
} = user;
```

を混乱せずに読めるのではないでしょうか？

似たような記述をしていますが、意味は全く違います。

<details><summary>上記の意味の確認はこちらをクリック</summary>

```ts:
nickname: userName
```

は、プロパティ名とは別名を変数に定義、

```ts:
programmingSkills: { frontEnd }
```

は、ネストしたオブジェクトです。

</details>

### 7.4. まとめ

最初は、簡単な分割代入でさえ読むことができませんでしたが、  
分割代入を使用しない書き方に変換することで、複雑な分割代入を自分で作れるまでになりました。

この記事を作成することで、分割代入を克服できたのかなと思います。

今後、Hooks にも挑戦していきたいと思います。  
ここまでできるようになったので、理解できるはず！！

併せて他の記事も読んでいただけると嬉しいです🙇‍♂️

https://qiita.com/daishiman/items/5acf803f252b82f970fe

https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf

## 参考
[書籍：プロを目指す人のためのTypeScript入門　鈴木僚太［著］](https://twitter.com/uhyo_/status/1517158176365641729?s=20&t=5jZBSZVbLrAsgkCUruO7Ig)