unique symbolについて理解する

# 目次
1. 背景
2. Symbolとは
3. ユースケース
4. unique symbolとは

# 1.背景
[Branded Type について理解する](https://qiita.com/yamatai12/items/e972833b3105883202a3)
この記事の中でunique symbolキーワードが出てきた為です。

[Symbols](https://www.typescriptlang.org/docs/handbook/symbols.html)
こちらを和訳し内容をまとめていきます。

# 2.Symbolとは
- 数値や文字列と同じように[プリミティブなデータ型](https://typescriptbook.jp/reference/values-types-variables/primitive-types#%E3%83%97%E3%83%AA%E3%83%9F%E3%83%86%E3%82%A3%E3%83%96%E5%9E%8B%E3%81%AE%E7%A8%AE%E9%A1%9E)です。
- Symbol constructorにより作成されます。

```javascript
const sym1 = Symbol();
const sym2 = Symbol(1); // 任意の数値
const sym3 = Symbol("key"); // 任意の文字列
const sym4 = Symbol(null);
const sym5 = Symbol(undefined);
const sym6 = Symbol(true); //真偽値
const sym6 = Symbol(9007199254740992n);//長整数型
const sym7 = Symbol({})//オブジェクト
const sym8 = Symbol([])//配列
```
- 不変で唯一の値です。
```javascript
let sym2 = Symbol("key");
let sym3 = Symbol("key");
sym2 === sym3; // false, symbolは一意の値なので等しくなりません。
```
:::note info
Symbol(Symbol())はエラーになリます。
Symbol constructorの引数にSymbol型を指定できません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/d1f46c9c-caf3-0b19-2ab3-e68648f2d37f.png)

[Cannot convert a Symbol value to a string](https://github.com/Microsoft/TypeScript/issues/12169)
対応方法
文字列型に変換してからSymbol constructorに渡します。
```typescript
Symbol(String(Symbol()))
Symbol(Symbol().toString())
```
:::

# 3. ユースケース
- オブジェクトのkeyとして使えます。
```javascript
const sym = Symbol();
let obj = {
  [sym]: "value",
};
console.log(obj[sym]); // "value"
```
- シンボルを[計算プロパティ宣言](https://qiita.com/yamatai12/items/c8f5fb56313f2e9362f5)と組み合わせて、オブジェクト・プロパティやクラス・メンバを宣言することもできます。
```javascript
const getClassNameSymbol = Symbol();
class C {
  [getClassNameSymbol]() {
    return "C";
  }
}
let c = new C();
let className = c[getClassNameSymbol](); // "C"
```

# 4.unique symbolとは
- シンボルを一意なリテラルとして扱えるようにするための型です。
- シンボルのサブタイプです。
  unique symbol型の変数をsymbol型の変数mySymbolに割り当てることができます。

```typescript
const myUniqueSymbol: unique symbol = Symbol();

let mySymbol: symbol;
mySymbol = myUniqueSymbol; // これは正しい、エラーが発生しない

// しかし、unique symbol型の変数に他のシンボルを割り当てることはできません
// myUniqueSymbol = Symbol(); // これはエラーになる
```
[playground](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAtgTwKpgJYEcCuBTAyguAIxABsAuGTNLbGCA4kmAXhnyNIAoBKAbgCh+JbLETtGFehxICxDUi3jJqOcaV4wA9JpiBlBkAxDIHsGQMbWgdQZAIgyBABkAVDIEuGQD8MgGQZAXm6B8V1OArBnODtMU4GkGU0sqDBw6eRJAaPVAOwZASE1AB1NAawZANblowHaGQGeGQB2GQGuGQCSGQCclQCiGQGV9QDMGQGiGXUALBkNAcwZAWQZAPwZAbQZAZIZ+X0QUULwIxTUSHg1fA0M7e0SPCqA)
- Symbol()やSymbol.for()、あるいは明示的な型アノテーションで作成されます。
- const宣言と読み取り専用の静的プロパティにのみ使用できます。
- ユニークなシンボルへの参照は、与えられた宣言に結びついた完全にユニークなアイデンティティを意味します。

```typescript
declare const sym1: unique symbol;

// sym2は定数宣言しかできません。
// let sym2: unique symbol = Symbol();
//A variable whose type is a 'unique symbol' type must be 'const'.

const sym2 = Symbol()
// 正常に動作します。見かけ上ユニークなシンボルを指しているが、そのアイデンティティは'sym1'に結びついています。
let sym3: typeof sym2 = sym2;
console.log(sym3 === sym2);//true

// こちらも正常に動作します。
class C {
  static readonly StaticSymbol: unique symbol = Symbol();
}
```
[playground](https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEYD2A7AzgF3mgngWwEYAueAVxQEsBHUhXPAIyQgG4AoNgek+3wCZA9gyAs7UAOpoGLtQABRgdQZA0gyBzBkCyDID8GQNoMgZIZAQAxceEEFnp8S5arV6Nm8ALzwAyviYQAFAEp23AILwAbrApQGuvAA7gAWSGgIGDgADggUaPBQ8ADkxjR09szJ8FGx8HikmPAMCMnI6BjJAHQc5UUGVraZTs7a8IDG1oAceoDWDICrSoA68lJKgJoMGoDRkTKAigyAUHKAZwyA0wyAPwyA9QyAVgyA7QyAzwyAOwyA1wyASQyA4MZSgGYMgCIMgNEMgDIMgIAMgLoMgHYMgEUMgCUMgOMMm4BjDIDFDD8CyfQCMluoAFX0AzgyAEwYzucRlpdPp8ABmEi5EBIABmZj4jQM7DqzBAVQgSAA5o56IirJZrAZXNwMDBaBxuPBAMoMgEMGQCRDIAghi6fUGsLYkCgaASAGF4ABvNjwbAYKAYChgeBwKDAVAQHC2eWKsB2cwQIyUdJmByNfUOFzsAC+HCAA)

# 参考
- [Symbols](https://www.typescriptlang.org/docs/handbook/symbols.html)

## 参考になる記事を書いてくださった皆様ありがとうございました！

## 宣伝させてください！
https://recruit.iimon.co.jp/