Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[新感覚パズルゲーム]type-challenges初級編へTry

はじめに

昨日のKPTで激ムズtype-challengesについて盛り上がったので、今度はしっかり学びながら問題を解いていき、まとめていこうと思います。
type-challenges

さっそく

warm up

問題1

  • 僕の解答↓
anser.ts
/* _____________ 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>

問題

  • 僕の解答
anser.ts
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>

問題

  • 僕の解答
anser.ts
/* _____________ 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じゃないって。。。
途中で諦めてごめんなさい。

yoshii0110
あくまで個人の見解なので、その点はご容赦下さい。
kddi
KDDIは、通信を中心に周辺ビジネスを拡大する「通信とライフデザインの融合」をより一層推進し、国内はもとよりグローバルにおいても、5G/IoT時代における新たな価値創造を実現し、お客さまの期待を超える新たな体験価値の提供を追求してまいります。
http://www.kddi.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away