はじめに
- こんにちは ! KDDI アジャイル開発センターの小板橋です。
- 昨日のKPTで激ムズtype-challengesについて盛り上がったので、今度はしっかり学びながら問題を解いていき、まとめていこうと思います。
type-challenges
さっそく
warm up
- 僕の解答↓
/* _____________ Your Code Here _____________ */
type HelloWorld = string // expected to be a string
/* _____________ Test Cases _____________ */
import { Equal, Expect, NotAny } from '@type-challenges/utils'
type cases = [
Expect<NotAny<HelloWorld>>,
Expect<Equal<HelloWorld, string>>
]
- 解説
ジェネリクスについて知っていれば、わかる問題かなという感じです。
ジェネリクスってなんやねん?
基本的に、型がある言語にはジェネリクスというものがよく存在しています。
これは、クラス、インターフェース、メソッドなどの型をパラメータとして定義することです。
もちろんTypeScriptにもジェネリクスがあります。
書き方としては、型名をHoge<S, T>
のようにします。
名前のあとに<>
で囲った変数の列を与えることで、型の定義の中でそれらを型の変数として使うことができるのです。
また、この問題だと<HelloWorld, string>
このジェネリクスに対しEqualを取っているので、type HelloWorld = string
としてやれば良い。
easy
Pick<T, K>
- 僕の解答
type MyPick<T, K extends keyof T> = {[k in K]: T[k] }
/* _____________ Test Cases _____________ */
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
MyPick<Todo, 'title' | 'completed' | 'invalid'>,
]
interface Todo {
title: string
description: string
completed: boolean
}
interface Expected1 {
title: string
}
interface Expected2 {
title: string
completed: boolean
}
- 解説
注目すべき点としては、まずK extends keyof T
という部分ですかね。
これは、型引数Kは型引数Tの部分型でなければならないうえ、typeof演算子を用いているので、与えられた値の型を文字列で返した時の部分型ということになります。
{[k in K]: T[k] }
については、まず右側の: T[k]
について明記する。
これは、Tが{ title: string; description: string; completed: boolean; }の型であることを指す。
次に、Mapped typesである[k in K]
を知っている必要がある。
Mapped typesとは、Kはstringにアサイン可能なtypeであればよく、Kに対する値はTというtypeになるという意味です。
参照: Mapped types
Readonly<T>
- 僕の解答
/* _____________ Your Code Here _____________ */
type MyReadonly<T> = { readonly [K in keyof T]: T[K] }
/* _____________ Test Cases _____________ */
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>,
]
interface Todo1 {
title: string
description: string
completed: boolean
}
- 解説
まず、[K in keyof T]: T[K]
ここは良さそうですね。先ほどの問題と似ています。
さて、ではreadonly
こいつですが、何をしているのかというと、これを付けることで、宣言されたプロパティは再代入できなくしています。constみたいなもの。
なので、テストケースを見た際にExpect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>
となっていると思いますが、右側のReadonly<Todo1>
でTodo1の型に対し、左側のMyReadonly<Todo1>
では型の制約([K in keyof T
、型引数Kは型引数Tの部分型でなければならないうえ、typeof演算子を用いているので、与えられた値の型を返した時の部分型)となっているので、付き合わせて時にイコールとなり、テストをクリアしていることになります。
おわりに
いや、難しすぎる。。easyじゃないって。。。
途中で諦めてごめんなさい。