1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-03-05

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

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

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

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

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

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

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

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

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

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

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

T2

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

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

T3

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

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

T4

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

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

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

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

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

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

となります。

T5

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

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

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

T6

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

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

T7

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

Pick

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

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

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

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

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

参考

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?