【TypeScript】TypeChallengesのeasy解法
公開
更新
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'>>>
Expext と Equal は問題側が用意している独自の判別関数みたいなもので、
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]