前回の記事でも話したのですが、
わからなかった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
}
そして
型情報は
第二引数に渡されたリテラルからプロパティ名が渡され、型情報には第一引数で渡された型情報のプロパティとマッチする型が入ります。
一つずつやれば理解できることを改めて学びました......
参考
強くなりたい!!!!!!!