【TypeScript】TypeChallengesのeasy解法

公開
更新
Photo by Minh Pham

TypeChallengesとは


TypeChallengesはTypeScriptの型付けを練習するための問題集です。


warm-up ~ extremeまで5段階で難易度が分かれています。
筆者はeasyがやっと解けるレベルです・・・。


easy実務でなんとかやっていけるレベルだと思います。
TypeChallengesは、TypeScriptの知識があるが高度な型付けは行えない人向けの問題集です。


今回はeasyの解法を順に解説していきます。
1問目は問題の見方など詳しく解説しています。


やり方などもっと詳しく知りたい方はこちらを参考にしてください。
TypeScriptの"型"を学びたいあなたへ。type-challengesのすゝめ

Pick

問題

/* _____________ Your Code Here _____________ */
type MyPick<T, K> = any

/* _____________ Test Cases _____________ */
import { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
  Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
  // @ts-expect-error
  MyPick<Todo, 'title' | 'completed' | 'invalid'>,
]

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
}

interface Expected2 {
  title: string
  completed: boolean
}


問題の見方


この部分に注目
Expect<Equal<Expected1, MyPick<Todo, 'title'>>>


ExpextEqual は問題側が用意している独自の判別関数みたいなもので、
Expect = 期待Equal = 同値なので、

Equal<type, type>の第1型引数と第2型引数は同値が期待される
その場合、MyPick型はどういう型になるかということを表しています。


MyPick型は初期状態なのでこのままではコンパイルエラーが出ます。
コンパイルエラーをどうやったら失くせるかを考えます。


今後の問題全てこの構成です。

答え&解説

type MyPick<T, K extends keyof T> = {[Key in K]: T[Key]}


期待されるのは、Todo型のプロパティの一部を持つオブジェクト型になるので、

・KはT(Todo型)のキー
・keyofでKはTのプロパティのUnion型に含まれるという制約を設ける
・Kからin演算子を使って単体でTのキーを取り出す
・ブラケット記法(T[K])でバリューを表現する。

First of Array


type First<T extends any[]> = T[0] extends T[number] ? T[0] : never 


or

type First<T extends any[]> = T[number] extends never ? never : T[0]


or

type First<T extends any[]> = T extends [] ? never : T[0]


or

type First<T extends any[]> = T extends [infer F,... infer L]?F:never


条件分岐

type タイプ名<型変数 extends 制約,...> = 型変数 extends 条件 ? 真の型 : 偽の型


Length of Tuple


type Length<T extends readonly any[]> = T extends [] ? 0 : T['length']



Awaited 


type MyAwaited<T extends Promise<any>> = T extends Promise<infer U> ? (U extends Promise<any> ? MyAwaited<U> : U) : T


IF


type If<C extends boolean, T, F> = C extends true ? T : F


Concat


type Concat<T extends any[], U extends any[]> = [...T, ...U]


Includes


type Includes<T extends readonly any[], U> = T extends [infer F, ...infer V] ? Equal<F, U> extends true ? true : Includes<V,U> : false;


Push

type Push<T extends any[], U> = [...T, U]


Unshift

type Unshift<T extends any[], U> = [U, ...T]


輝良 / Kira

HTML, CSS, JavaScript, Vueを勉強して、未経験から独学でフロントエンドエンジニアへ転職。 実務ではTypeScriptとVueを使用。モダンフロントエンド技術が好き。 当サイトはNuxt3+TS+TailwindCSS+microCMSで構築。