TypeScript: in、Mapped Type [アウトプット全くしてこなかったのでアウトプットする006]

https://qiita.com/cawauchi/items/0fea0540e3d47d64b9fb

前回の記事でも話したのですが、
わからなかったtype-challengeの問題をここでまた載せます

https://www.typescriptlang.org/play?#code/PQKgUABBAsELQQAoEsDGBrS8491gRgJ4QCCAdgC4AWA9mcQGICuEAFAAICGlAZkwJQQAxIFwlQFi+wpmWR1h+JsgA2FOMjJYsQrREBXMYHlVDVEAivoH8GQD3xJwHYMgaPVAZwyAfhkBjDIGKGQFcMLgAYoMAHgAqADQQANIAfB6ASQyA-vKAFK6A2gyAWgyAgAwefh6A0gyAkQwewR6WgOsMgLcMgIsMLhGAvUaAX4qAmgyA0QzWEYD52oCjEYDqDIB+DNWAQAyGEIDR8oASDIAODL0eYxQAzlhqFACmAE48nKizEH40ACY0EADeWFAUyBSKswBcEBMU82oA5vsQG7MTqNcADod055fXZHdQUKgaABbV4nOYbc74Gg0E7cLAAX16FEIr1W6y2iHmswAbshZgB3CAAXggAFlCN50P5NjQggByQ7HWZ0iAAHwgdMBILBsw2dNCvUBZEuEAoNPO6JomJxeMJJL2-3+jJO5zpAGFYWQIPNoUC6QF7gDgaDZuDzktFBNZgaoIioGMPL1QhAAOJHAASTHwgHMGQBdHoBYqLqgCx-qgUCivCanYDASaoKgAOgAVhN4zR5jdgNBgInOGAQMAwIXQBAAPpl8sV8sQQDKDNXANYMgGaGeyASYYIoAMKMApoqlys9ksQfOF5GoskUtBUwIhZ0k7iEQtgYu9nsQRyAToZABMMgEaGewr7uLqsD5AgtMUXYQACiAEcmJxFEEzwAPVGoE-wiA8HVAjnsIezOBxm8nL8TzAEwhyWnSg4oqsqCcFaEzEhAADaWAPk+FA+Je16KBhj6zM+vIAIxBOSlLUls9LKsyoTUTa564c+GFXjeOFobyABMxGjr4koUUcJwsuynLGjyfLUaEtHRhA34THAsz0SoCw6vMWAkWOZG0hylECRyXImuC2l0mo2I3sgokGgAuoWMwLEsKxrDSuxYJRXxXLcWCPM8bwfGQLk-H8EC6SJkLQpqYCImA1mLMsqyoXh4IEY5Bx8WcFyub8YVWZQNnRXRrEbGxiWislvluUa3KmrywUwrMcLhUWIC7nufaAITWlgro4gDDDPkjV7v2BagFgzqAMeRgAq3hEgCOioAkObBqG4aRtGsYJsmqbppmwDcBM+ILNmuZQMNY2ANGRtQhmGEZRjGzxLSmaYZlmEwwqBMjCoNECALoMliAGtyliAE1RgAyGSdc3nYtSbXatOZ5gWYBAA

この問題はUtility Typeである`Pick`を自分で実装しろという問題でした。

```ts
type Pick<T,K extends keyof T> = {
  [P in K]:T[P]
}
```

ちなみに答えは上記です。
`extends`は全記事でやったので`in`をアウトプットしていきます

まずぱっと見`[P in K]`の部分の理解が曖昧です。

以下コピペですがここから読み解いていきます。

```ts
type Item = { a: string, b: number, c: boolean };

type T1 = { [P in "x" | "y"]: number };  // { x: number, y: number }
type T2 = { [P in "x" | "y"]: P };  // { x: "x", y: "y" }
type T3 = { [P in "a" | "b"]: Item[P] };  // { a: string, b: number }
type T4 = { [P in keyof Item]: Date };  // { a: Date, b: Date, c: Date }
type T5 = { [P in keyof Item]: Item[P] };  // { a: string, b: number, c: boolean }
type T6 = { readonly [P in keyof Item]: Item[P] };  // { readonly a: string, readonly b: number, readonly c: boolean }
type T7 = { [P in keyof Item]: Array<Item[P]> };  // { a: string[], b: number[], c: boolean[] }
```
コピペ元: https://qiita.com/Quramy/items/e27a7756170d06bef22a#keyof

#### T1

```ts
type T1 = { [P in "x" | "y"]: number };  // { x: number, y: number }
```

これはプロパティであるPは "x"と"y"のリテラル型というもので型であるnumberはもうこれになることが決まっています。(表現下手)

https://typescriptbook.jp/reference/values-types-variables/literal-types

もし以下だったら結果の方はどうなると思いますか?

```ts
type ExampleT1 = { [P in "x" | "y"]: string | number };}
```

#### T2

```ts
type T2 = { [P in "x" | "y"]: P };  // { x: "x", y: "y" }
```

これは
リテラル型である "x"と"y"をプロパティにしてさらにPをkeyに渡しています。
なんかここら辺のPを一旦保存して型情報に渡すっていうのがぱっと見とっつきにくいような気がしていますが、これを計算しているTypeScriptすげえなって思います。

#### T3

```ts
type T3 = { [P in "a" | "b"]: Item[P] };  // { a: string, b: number }
```

これはリテラル "a"と"b"をプロパティに渡して型情報にはItemの中からプロパティ"a"とプロパティ"b"を引っ張ってきています。

#### T4

```ts
type T4 = { [P in keyof Item]: Date };  // { a: Date, b: Date, c: Date }
```

これは`keyof`のせいで一瞬「うっ.....」となるのですが、
冷静にkeyofの意味がわかれば解けます。

以前keyofについてはアウトプットしました。

https://qiita.com/cawauchi/items/09e1894e390da5ad255d#:~:text=number%3B%0A%20%20y%3A%20number%3B%0A%7D%3B-,keyof,-keyof%E3%81%AF%22%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88

keyofはTypeからプロパティをリテラル型で渡してくれます。

なので`keyof Item`で渡されるのは `"a" | "b" | "c"`　になります
これをわかりやすくすると

```ts
type Example4 = { [P in "a" | "b" | "c"]: Date };  // { a: Date, b: Date, c: Date }
```

となります。

#### T5

```ts
type T5 = { [P in keyof Item]: Item[P] };  // { a: string, b: number, c: boolean }
```

これはT3とT4の合わせ技ですね

Pには`"a" | "b" | "c"`が渡され、型情報にはItemの中からプロパティPの型が渡されます。

#### T6

```ts
type T6 = { readonly [P in keyof Item]: Item[P] };  // { readonly a: string, readonly b: number, readonly c: boolean }
```

T5の型にreadonly型をつけただけですね

#### T7
T7は書くの力尽きました。

#### Pick

```ts
type Pick<T,K extends keyof T> = {
  [P in K]:T[P]
}
```

ジェネリクスの第一引数に渡したい型を渡す
ジェネリクスの第二引数には第一引数で渡された型のプロパティが制約として渡される
例えば第一引数の型が以下であれば 文字列 "a"と"b"のみ渡すことができます。

```ts
type T = {
  a: string,
  b: number
}
```

そして
型情報は
第二引数に渡されたリテラルからプロパティ名が渡され、型情報には第一引数で渡された型情報のプロパティとマッチする型が入ります。

一つずつやれば理解できることを改めて学びました......

## 参考
https://qiita.com/Quramy/items/e27a7756170d06bef22a

強くなりたい!!!!!!!