[TypeScript]組み込みの型を使いこなす

# はじめに
組み込みの型について学んだので、備忘録として書いていきます。

# 組み込みの型とは
TypeScriptでは、「mapped types」や「conditional types」により可能となった操作のうち、特に有用なものが、組み込み型として、標準ライブラリとして用意されています

# Readonly
Readonlyは、定義したオブジェクトのプロパティを全て読み取り専用にする機能です。

```ts
type T = Readonly<{
  name: string;
  age: number;
}>;

// Tは{
//   readonly name: string;
//   readonly age: number;
// }

const person: T = {
  name: "Alice",
  age: 30,
};

// エラー: 'name' プロパティは読み取り専用です
// person.name = "Bob";

// エラー: 'age' プロパティは読み取り専用です
// person.age = 31;
```
このように、「type T」に「Readonly」を付けると、中身のデータは読み取り専用となり、後からプロパティの内容を変更できなくすることができます。
これを使用することで、安全にデータを管理できるようになります。

# Pick

Pick<T, K>は、Tという名前で定義したプロパティの中から、Kという名前のプロパティのみを残したオブジェクト型を表すことができます。
「type Q」を例にしてみると、「name」と「age」の二つのプロパティが設定されたオブジェクトにPickを設定し、第二引数に「age」を指定すると、「type Q」は、「age」のみを持つオブジェクト型として作られます。
また、二つ目の例にあるように、複数のプロパティを第二引数に設定することも可能です。

```ts
type Q = Pick<
  {
    name: string;
    age: number;
  },
  "age"
>;

type O = Pick<
  {
    name: string;
    age: number;
  },
  "age" | "name"
>;

const objQ: Q = {
  age: 30,
};

const obj: O = {
  name: "sato",
  age: 40,
};

// エラー: 'name' プロパティは存在しません
// obj.name = "Alice";

console.log(obj.age); // => 40
```

以下のように、オブジェクトを別で定義し、場面ごとで、取り出すプロパティを変更できるようにすることもできます。

```ts
type Human = {
  name: string;
  age: number;
  adress: string
}

type Q = Pick<
  Human,
  "age" | "adress"
>;

type O = Pick<
  Human,
  "age" | "name"
>;

const objQ: Q = {
  age: 10,
  adress: "sample"
};

const obj: O = {
  name: "sato",
  age: 40,
};
```
同じようなプロパティを含むオブジェクトを複数使う場合に使えますね。

# Partial, 
Partialは、全てのプロパティをオプショナルにすることができます。
```ts
type P = Partial<{
  name: string;
  age: number;
  adress: string
}>;

// Tは{
//   name: string | undefined;
//   age: number| undefined;
// }

const partialPerson: P = {};

// 'name' プロパティと 'age' プロパティがオプショナルなので、インスタンスを作成する際に指定しなくてもよい
// 'name' と 'age' はどちらも undefined となる
console.log(partialPerson.name); // => undefined
console.log(partialPerson.age); // => undefined

partialPerson.name = "Alice";
partialPerson.age = 30;
partialPerson.adress = undefined;

console.log(partialPerson.name); // => "Alice"
console.log(partialPerson.age); // => 30

```

# Extract

Extract<T, U>は、Tに設定した構成要素のうち(普通はユニオン型)、Uの部分型であるもののみを抜き出して、新しいユニオン型を定義することができます。

```ts
type Union4 = "hukuryo" | "kenta" | 1 | 2 | 3;

type ExtractString = Extract<Union4, string>;

const union4: ExtractString = "hukuryo";
const union5: ExtractString = "kenta";
// エラー
// const union1: ExtractString = 1;
// const union2: ExtractString = 2;
// const union3: ExtractString = 3;

type ExtractNumber = Extract<Union4, number>

const union6: ExtractNumber = 1
const union7: ExtractNumber = 2
const union8: ExtractNumber = 3

// エラー
// const union10: ExtractNumber = "hukuryo";
// const union9: ExtractNumber = "kenta";
```


# Exclude
Exclude<T, U>は、Extract<T, U>の逆で、Tに設定した構成要素のうち(普通はユニオン型)、Uの部分型であるもののみを取り除いた、新しいユニオン型を定義することができます。
```ts
type Union5 = "hukuryo" | "kenta" | 1 | 2 | 3;

type ExcludeUnion = Exclude<Union5, string>;

const union1: ExcludeUnion = 1;
const union2: ExcludeUnion = 2;
const union3: ExcludeUnion = 3;
// エラー
// const union6: ExcludeUnion = "hukuryo";
// const union7: ExcludeUnion = "kenta";

```

# まとめ
組み込みの型を利用することで、コードの量を減らすとともに、可読性の高い型定義をすることができます。
積極的に活用して、簡潔な型定義をできるようにしましょう。

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください、、、

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11