【Typescript】実戦で使えそうな組み込み型関数

# はじめに
普段はvue・Typescriptで主に開発しているのですが、Typescriptで提供されている
**utilityTypes** をあまり使わずに開発していることが多かったので使用していきたいと思い、使えそうなやつをピックアップして紹介します！


# Pick< T, K >

既に用意されているTypeから必要な項目だけを抜き出した新しい型を作りたい時に使用する`

```typescript
type Person = {
	name: string;
	age: number;
	email: string;
	address: string;
}

type PickedPerson = Pick<Person, 'name' | 'age'>
// => type Student = {name: string, age: number}と同義

const taro: PickedPerson = {
    name: 'Taro',
    age: 10,
}
```

# Partial< T >
存在する型の全てをOptionalのプロパティに変換する

```typescript
type Person {
    name: string;
	age: number;
	email: string;
	address: string;
}

type PartialPerson = Partial<Person>
// Person型の全てのプロパティをOptionalに変換

const taro: PartialPerson = {
  name: 'Taro',
}
// => age, email, addressがなくてもエラーにならない
```

# Required< T >
全てのプロパティを必須のプロパティに変換する

```typescript
type Person {
  name?: string;
	age?: number;
	email?: string;
	address?: string;
}

type RequiredPerson = Required<Person>
// Person型の全てのプロパティを必須プロパティに変換

const taro: RequiredPerson = {
  name: 'Taro',
}
// エラー => age, email, addressがないのでエラー

```

# Omit< T, K > 
既に存在する型の中から選択した一部のプロパティを除いて新たな型を作成する。
Pickの逆ですね。

```typescript
type Person = {
    name: string;
	age: number;
	email: string;
	address: string;
}

type OmittedPerson = Omit<Person, 'name'>
// => Personから'name'を除いた型を作成

const taro: OmittedPerson = {
    age: 10,
	email: 'test@example.com'
	address: 'test5-57-5'
}

```

# Record< Keys, Type >
プロパティのキーがKeysであり、プロパティの値がTypeであるオブジェクト型を作る

```typescript
type Person = Record<"firstName" | "middleName" | "lastName", string>;

const person: Person = {
  firstName: "花子",
  middleName: "duran",
  lastName: "田中",
};
```

もっと踏み込むと以下の様な使い方ができます。

```typescript
type Animal = {
  name: string;
  age: number;
}

type List = {
  lion:Animal;
  dog:Animal;
  cat:Animal;
}
 
const list:List = {
  lion: { name:'lion',age:4 },
  dog: { name:'dog',age:15 },
  cat: { name:'saburo',age:18 },
}


```
`List`型のキーは全て`Animal`である。ここをなんとかしたい。
`Record`を使い以下の様にする。

```typescript
type Animal = {
  name: string;
  age: number;
}

type List = 'lion' | 'dog' | 'cat';
 
// Listのユニオンタイプ('lion' | 'dog' | 'cat')がキー、 Animalが値の型を作成する
const list:Record<List,Animal>= {
  lion: { name:'lion',age:4 },
  dog: { name:'dog',age:15 },
  cat: { name:'saburo',age:18 },
}
```

# ReturnType< T >
関数の戻り値の型から新たな型を生成します

```typescript
type StringType = ReturnType<() => string>; // 返り値がstringの関数
// type StringType = string

type ObjectType = ReturnType<(value: string) => { name: string; old: number }>; // 返り値がオブジェクトの関数
// type ObjectType = { name: string; old: number; }

const callStudent = (student: string, teacher: string): void => {
  console.log(`${teacher}: 元気ですか？　${student}:　はい元気です！`);
};

type CallType = ReturnType<typeof callStudent>; // 返り値がvoidの関数
// type CallType = void
```

# 番外編
# Conditional Types
型定義の際に三項演算子を使える

```typescript
type IsString<T> = T extends string ? true : false
// Tの型がstringかどうかで判定される

type A = IsString<'a'>     // type A = true
type B = IsString<1>       // type B = false
type C = IsString<boolean> // type C = false
```

`Conditonal Types`は`never`型と組み合わせることが多いので、never型の特性について紹介すると
never型にはどんな値もセットできない型なので、`T | never`というUnion型は`T`になります。
つまり、`never型`は排除されるということです。
以下never型を条件に入れてConditional Typesを利用した例です。

```typescript
type Student = {
  name: string;
  grade: number;
}

type Teacher = {
   name: string;
   age: number;
   role: string;
}

type Animal = {
    name: string;
	age: number;
}

type SelectedPerson = Student | Teacher;

// SelectedPersonを満たす型のみをフィリタリングする。
// falseの時はnever型つまり排除される
type SelectedPersonFilter<T> = T extends SelectedPerson ? T : never;

// Animalは SelectedPersonを満たさないので SelectedPersonTypeから除外されている
type SelectedPersonType = SelectedPersonFilter<Student | Teacher | Animal>
// type SelectedPersonType = Student | Teacher
```

# 最後に
**utility types**はせっかく用意してくれているのに使用していないことが多かったので
今後は使用していこうかなと思いました。
誰かの参考になれば幸いです。