0歳娘「パパ、型を作る関数はないの？」

## 2015年、とある休日

よめ太郎「あ・・・あんた！」
よめ太郎「こっち来て！！！」

ワイ「ど、どうしたん？」
ワイ「えらい大っきい声出して」

よめ太郎「娘ちゃんが初めて立ったんや！」

娘（**0歳**）「ヨチ・・・ヨチ・・・」

ワイ「おお・・・！」
ワイ「これはめでたいこっちゃ・・・！」

娘「・・・パパァ・・・」

ワイ「！？」
ワイ「いま、**パパ**言うたで！？」
ワイ「立ったと同時に言葉も喋れるんか！？」
ワイ「なんて末恐ろしい子や・・・！」

娘「・・・エテ・・・教エテ・・・」

ワイ「な、なんや喋っとるで・・・」
ワイ「なんや、娘ちゃん・・・？」

娘「・・・パパ・・・」
娘「・・・プログラミング・・・教エテ・・・」

ワイ「ファッ！？」
ワイ「`Hello, World!`でええか・・・？」

よめ太郎「いや、`Hello, World!`は**産声で言うてたわ**」

ワイ「せやった！」
ワイ「お医者さんが思わず・・・」

> 医者「リアルHello Worldしてどないすんねん」

ワイ「ってツッコんでたもんな」
ワイ「ほな、今日は何を教えてほしいんや？娘ちゃん・・・」

娘「・・・ええと・・・」
娘「実は、こないだ**6ヶ月検診**で行った病院から依頼を受けて」
娘「とある**管理画面**のフロントエンド部分を開発してるの」

ワイ「**もう実務！？**」
ワイ「凄いやないか・・・」

よめ太郎「普通に受け入れてるお前が凄いわ」

ワイ「それで、どんな管理画面なんかいな？」

娘「幼児たちの身体測定の結果を記録するための管理画面なの」

ワイ「ふむふむ」

娘「それでね？」
娘「子供たちの身長とか体重、氏名などを記録する必要があるから」
娘「TypeScriptで、こんな**型**を定義したの」

```typescript
type Child = {
    lastName: string
    firstName: string
    age: number
    height: number
    weight: number
}
```

ワイ「なるほどな」

> - 子供は、姓・名・年齢・身長・体重というプロパティを持っている。

ワイ「・・・ということを表しているんやな」
ワイ「ええ感じやないか」
ワイ「それで、いったい何が分からへんのや？」

娘「えっとね」
娘「氏名や年齢を入力して、子供たちの情報を**検索**する画面があるんだけど」
娘「そこで使う型が上手く書けないの」

ワイ「と言いますと？」

娘「例えば、氏名で検索する場合は」

```typescript
const condition: Child = {
    lastName: "やまだ",
    firstName: "たかし"
}
```

娘「↑こんな感じの条件になるんだけど」
娘「型が合わなくて、エラーになっちゃって」

> 次のプロパティがありません：
> age, height, weight

娘「↑こんなエラーが表示されちゃうの」

ワイ「なるほどな」
ワイ「`Child`型のはずなのに、姓と名しか持ってないから・・・」

> 「**年齢**と**身長**と**体重**が足りまへんがな！」

ワイ「って怒られとるわけやな」
ワイ「そういう場合は、こんな型を書けばええで」

```typescript
type PartialChild = {
    lastName?: string
    firstName?: string
    age?: number
    height?: number
    weight?: number
}
```

ワイ「プロパティ名の後ろに`?`を付けてやるんや」
ワイ「姓・名・年齢・身長・体重というプロパティを、全て持っててもいいし」
ワイ「一部だけ持っててもいい、そんな型や」
ワイ「ちなみに`Partial`ってのは、**部分的**って意味や」

```typescript
const condition: PartialChild = {
    lastName: "やまだ",
    firstName: "たかし"
}
```

ワイ「↑ほら、`PartialChild`型にしたらエラーが消えたで」

娘「パパ、**そんなことは知ってるの**」

ワイ「ファッ！？」

娘「そうじゃなくて」

```typescript
type Child = {
    lastName: string
    firstName: string
    age: number
    height: number
    weight: number
}

type PartialChild = {
    lastName?: string
    firstName?: string
    age?: number
    height?: number
    weight?: number
}
```

娘「↑こんな風に」
娘「**ほぼ同じ型**を2回も書くのが冗長だから」
娘「もっと効率的な書き方はないのか、ってことを聞きたいの」

ワイ「ぐぬぬ・・・」

娘「`Child`型を元に`PartialChild`型を作ってくれるような」
娘「そんな、**型を作る関数**みたいなのはないの？」

ワイ「誠に残念ながら、ございませんねや・・・」

#### よめ太郎「あるで」

ワイ「ファッ！？」

## Partial&lt;Type&gt;

よめ太郎「ほな、コードを書きながら説明していくで」
よめ太郎「`Child`型を元に`PartialChild`型を作るには・・・」

```typescript
type PartialChild = Partial<Child>
```

よめ太郎「↑こうや」

娘「へえ、`Partial`ってやつに`Child`型を渡すと」
娘「さっきの`PartialChild`型と同じものを作って返してくれるんだ！」

よめ太郎「せや」

娘「じゃあ、逆に`PartialChild`型から`Child`型を作るようなやり方もあるの？」

よめ太郎「あるで」

## Required&lt;Type&gt;

```typescript
type PartialChild = {
    lastName?: string
    firstName?: string
    age?: number
    height?: number
    weight?: number
}
```

よめ太郎「↑この型を元に・・・」

```typescript
type RequiredChild = {
    lastName: string
    firstName: string
    age: number
    height: number
    weight: number
}
```

よめ太郎「↑この型を生成したい場合は・・・」

```typescript
type RequiredChild = Required<PartialChild>
```

よめ太郎「↑こうや！」

娘「へえ、`Required`っていうやつに、`PartialChild`を渡すと」
娘「全部のプロパティから`?`マークを取ってくれるんだね！」

よめ太郎「そんなイメージや」

## Readonly&lt;Type&gt;

娘「じゃあママ」
娘「次は・・・プロパティを上書きできない**readonly**な型を作って！」

よめ太郎「ええで」
よめ太郎「つまり・・・」


```typescript
type Child = {
    lastName: string
    firstName: string
    age: number
    height: number
    weight: number
}
```

よめ太郎「↑この`Child`型を元に・・・」

```typescript
type ReadonlyChild = {
    readonly lastName: string;
    readonly firstName: string;
    readonly age: number;
    readonly height: number;
    readonly weight: number;
}
```

よめ太郎「↑こんな型を作ればええんやろ？」

娘「そう！」

よめ太郎「その場合は・・・」

```typescript
type ReadonlyChild = Readonly<Child>
```

よめ太郎「↑こうや！」

娘「わぁ、便利だね！」

## Omit&lt;Type, Keys&gt;

娘「じゃあママ」
娘「`Child`型から、`height`プロパティと`weight`プロパティだけ削って」

```typescript
type NameAndAge = {
    lastName: string
    firstName: string
    age: number
}
```

娘「↑こんな型を作ることもできる？」

よめ太郎「できるで」

```typescript
type NameAndAge = Omit<Child, "height" | "weight">
```

よめ太郎「↑こうや！」

娘「わあ、便利！」

ワイ「（いつ便利やねん・・・）」

※筆者注：**割と使うときあります。**

## ReturnType&lt;Type&gt;

娘「じゃあママ」
娘「例えば・・・」


```typescript
const sameCheck = (a: number, b: number): boolean => a === b
```

娘「↑こんな`sameCheck`っていう関数があるとして」
娘「この関数の、**戻り値の型**を求めることはできる？」

よめ太郎「できるで」

```typescript
type SameCheckReturnType = ReturnType<typeof sameCheck>
```

よめ太郎「↑こうや」

娘「へえ、`ReturnType`ってやつに`typeof sameCheck`を渡すと」
娘「`sameCheck`関数の**戻り値の型**を取得できるんだ！」

よめ太郎「せや」
よめ太郎「今回の場合、`SameCheckReturnType`型は`boolean`型になるっちゅうことやな」

娘「なるほどね〜」

よめ太郎「もし`sameCheck`関数の戻り値の型が変わった場合でも」
よめ太郎「`SameCheckReturnType`型も**追従して変わってくれる**から」
よめ太郎「ベタ書きで`boolean`って書くより便利やで」

娘「なるほどね！」
娘「ある関数の型を変更した場合に」
娘「連動して他の部分の型も変わってくれるってことだね」
娘「たまに便利そうだね！」

よめ太郎「そういうことや」

## Parameters&lt;Type&gt;

よめ太郎「逆に、ある関数の**引数の型**を取得したい場合は」

```typescript
type SameCheckParametersType = Parameters<typeof sameCheck>
```

よめ太郎「↑こうや」

娘「へえ、`sameCheck`関数には**引数が2つ**あるけど」
娘「どんな形式で返ってくるの？」

```typescript
type SameCheckParametersType = [a: number, b: number]
```

よめ太郎「↑こんな感じや」

娘「へぇ、引数の型は**タプル型**で返ってくるんだね」

よめ太郎「せや」

## Exclude&lt;Type, ExcludedUnion&gt;

娘「じゃあママ」

```typescript
type Food = "カレー" | "オムライス" | "ラーメン" | "餃子"
```

娘「↑この`Food`型から、中華料理だけを**除外したい**場合は？」

```typescript
type FoodExcludeChinese = Exclude<Food, "ラーメン" | "餃子">

/*
FoodExcludeChinese型は
"カレー" | "オムライス"
となる
*/
```

よめ太郎「↑こうやな」

```typescript
type Chinese = "ラーメン" | "餃子"
type FoodExcludeChinese = Exclude<Food, Chinese>
```

よめ太郎「↑こうでもええで！」

娘「なるほど〜」
娘「**Exclude**って、**除外する**って意味だもんね！」

## Extract&lt;Type, Union&gt;

娘「じゃあママ」


```typescript
type Hoge = 1 | 2 | 3 | 'a' | 'b' | 'c' | true | false
```

娘「↑この`Hoge`型から、`true`と`false`だけ除外したい場合は？」

よめ太郎「ええと、要は`boolean`を除外すればええから」
よめ太郎「さっきの`Exclude`を使って・・・」

```typescript
type HogeStringNumber = Exclude<Hoge, boolean>

/*
HogeStringNumber型は
1 | 2 | 3 | "a" | "b" | "c"
となる
*/
```

よめ太郎「↑こうやな」
よめ太郎「もしくは」
よめ太郎「`Hoge`型から**数値と文字列だけ抽出**した型を作る、と考えて」

```typescript
type HogeStringNumber = Extract<Hoge, string | number>
```

よめ太郎「↑こうでもええで」
よめ太郎「`Extract`は**抽出する**って意味やからな」

娘「へえ〜」

## 型関数
娘「すごいね」
娘「引数として型を渡すと、別の型が返ってくる・・・」
娘「**型を作る関数**みたいだね！」

よめ太郎「まさにそんな感じやな」
よめ太郎「せやから、**型関数**って呼んどる人たちもおるで」
よめ太郎「正式な用語やないらしいけどな」

娘「へぇ〜、型関数か〜」

よめ太郎「[**TypeScriptの公式サイト**](https://www.typescriptlang.org/docs/handbook/utility-types.html)では、**Utility Types**って呼ばれてるみたいや」
よめ太郎「**お役立ち型**って意味やな」
よめ太郎「その名の通り、けっこう実務で役立つから」
よめ太郎「こんなのがある、ってことだけでも覚えておくとええで！」

娘「わかった！」
娘「ありがとう、ママ！」

よめ太郎「どういたしましてやで！」

娘「あっ！パパ！」

ワイ「なんや？娘ちゃん」

娘「ウンチ出た！」

ワイ「いやそこは赤ちゃんなんかい！」

**〜おしまい〜**


## 参考文献

この記事で書いた以外にも色々便利なのがあるから、是非読んでみてくださいやで！

- [**Handbook - Utility Types - TypeScript**](https://www.typescriptlang.org/docs/handbook/utility-types.html)
- [**TypeScript特有の組み込み型関数**](https://log.pocka.io/posts/typescript-builtin-type-functions/)

## 新しい記事もよろしくやで

[**5歳娘「パパ、型はドキュメントだよ？」**](https://qiita.com/Yametaro/items/1065eb96a7388f528319)