【TypeScript】プリミティブ型 / ユーザ定義型 を使った定義

## はじめに
- この記事では、`TypeScript` における`プリミティブ型` と `ユーザー定義型` について、まとめています。

## プリミティブ型とは
- プログラミング言語において、`プリミティブ型`とは`基本的なデータ型`のことを指します。
これらは言語によってあらかじめ定義されており、開発者が自由に構造や挙動を変えるということはできません。
- `TypeScriptにおけるプリミティブ型`は、以下の`7種類`になります。
  - まずはプリミティブ型を知ることが、TypeScript の第一歩です。
  - よく使うのは、下記の`Bigint と symbol 以外の型`ですね。


### `string`（文字列）
- "abc" のような `文字列` を表す
```tsx
const text: string = "abc";
const message: string = "Hello World";
```

### `number`（数値）
- 0, 1 のような 数値 を表す
  - 1, -1 などの`整数` と 0.1などの`小数` を含む
```tsx
const zero: number = 0;
const num: number = 111;
```

<details>
<summary>補足1</summary>

- number型には、`NaN` と `Infinity` という特殊な値がある


##### NaN
- 非数(not-a-number)を表す変数です。
JavaScriptでは、処理の結果、数値にならない場合にNaNを返すことがあります。
たとえば、文字列 を 数値 に変換するparseInt関数は、数値化できない入力に対し、NaNを返します。
```tsx
const price = parseInt("百円");
console.log(price); // NaN
```

- 値がNaNかどうかのチェックは `Number.isNaN` を使用
```tsx
const price = parseInt("百円");
if (Number.isNaN(price)) {
  console.log("数値化できません");
}
```

##### Infinity
- Infinityは無限大を表す変数。例えば、1 を 0 で割った場合に、この値になる

```tsx
const result = 1 / 0;
console.log(result); // Infinity
```
</details>



### `boolean`（真偽値）
- true または false の `真偽値` を表す
```tsx
const isOk: boolean = true;
const isWhite: boolean = false;
```

### `Bigint`（長整数）
- `9007199254740992n` のような `number型では扱えない大きな整数型` を表す
  - BigInt を使用するには、整数の末尾に`n`を付ける
  - BigInt型とnumber型を一緒には演算できず、どちらかに型を合わせる必要がある
  - number型が小数部を持っていない限り、表現幅の広いBigint型に合わせるのが無難
- ES2020 から導入
  - 比較的新しい機能で、古いブラウザでは利用できないこともあるため、ブラウザの互換性やPolyfillを検討する必要あり
  - コンパイラーオプション の target を es2020以上 にする必要あり
```tsx
const x: bigint = 100n;
const bignum: bigint = 9007199254740992n;
```

### `null`（値がない）
- 値が無いこと を表す
```tsx
const x: null = null;

// 値の型を調べる `typeof`演算子 を nullに対して用いると `"object"` が返るので注意が必要
console.log(typeof null); // "object"
```
<details>
<summary>補足</summary>

TypeScript では、`null`、`undefined`、`空文字列 ''`、`数値の 0`、`NaN`、および `false` はすべて `false` として評価する
</details>


### `undefined`（値が未定義）
- 値が未定義であること を表す
  - `変数に値がセットされていない時`、`戻り値が無い関数`、`オブジェクトに存在しないプロパティにアクセスした時`、`配列に存在しないインデックスでアクセスした時`など
```tsx
const y: undefind = undefind;

let name;
console.log(name); // undefined - 変数に値がセットされていない

function func() {}
console.log(func()); // undefined - 戻り値が無い関数
 
const obj = {};
console.log(obj.name); // undefined - オブジェクトに存在しないプロパティにアクセスした時
 
const arr = [];
console.log(arr[1]); // undefined - 配列に存在しないインデックスでアクセスした時
```

<details>
<summary>補足</summary>

`戻り値のない関数`は`undefined`になるが、`戻り値なし を 型注釈で表現する場合`は、undefinedではなく`void`を使用する

> 参照： [戻り値がない関数とvoid型 (void type)](https://typescriptbook.jp/reference/functions/void-type)
</details>


### `symbol`（一意の値）
- 一意（unique）で不変の値 を表す
- ES2015 から導入

```tsx
const sym: symbol = Symbol()

const s1 = Symbol("foo");
const s2 = Symbol("foo");

console.log(s1 === s1); // true
console.log(s1 === s2); // false

// boolean型 や number型 は 値が同じであれば、等価比較は true になる
// s1 === s1 は 同一のシンボルを比較しているため、結果は true になる
// s1 === s2 は 値が同じであっても、異なるsymbol を比較しているため、結果は false になる
```

<details>
<summary>補足</summary>

##### シンボルの用途
JavaScriptにシンボルが導入された動機は、JavaScriptの組み込みAPIの下位互換性を壊さずに新たなAPIを追加することだった。つまり、シンボル は JavaScript本体をアップデートしやすくするために導入されたものです。
したがって、アプリケーションを開発する場合に限っては、シンボル を駆使してコードを書く機会はそう多くない。

##### シンボルのメリットと使い所
symbol型 は 他のどの値とも重複しない、完全にユニークなプロパティキーをオブジェクトに追加する際に適していると言えます。名前の衝突を避け、データのカプセル化や拡張を安全に行えるようになります。
</details>




## ユーザ定義型とは
- `開発者 が 特定の要件に合わせて定義するデータ型` のこと
- つまり、上記までのプリミティブ型 を組み合わせたり、特定のルールや構造を有するオブジェクト、配列、関数などを`自由に定義して作成できるデータ型`のことを指します。
  - これにより、`より複雑なデータ構造やロジック`を表現することが可能になります
```tsx
// ユーザ定義型の例 （オブジェクト）
let person = {
    name: "Jane Doe",          // 文字列型のプロパティ
    age: 25,                   // 数値型のプロパティ
    isStudent: true,           // 真偽値型のプロパティ
    
    address: {                 // ユーザ定義型（オブジェクト）内のユーザ定義型（オブジェクト）
        street: "123 Main St",
        city: "Anytown",
        country: "USA"
    },
    
    sayHello: function() {     // 関数型のプロパティ
        console.log("Hello!");
    }
};
```


## まとめ
いかがだったでしょうか？

プリミティブ型 / ユーザ定義型 をそれぞれ理解し、最適な型を利用してコードを記述できるようにしていきましょう。


## 参考
https://typescriptbook.jp/reference/values-types-variables/primitive-types

https://typescript-jp.gitbook.io/deep-dive/type-system

https://qiita.com/muuuumiin3/items/d2456ccd4162ce82a810