復習:配列の最初の要素を取得する(TC-4)

お題

配列Tを受け取り、その最初の要素を返す型を実装する。

やりたいこと(具体)

type arr = ["a", "b", "c"]
type result = First<arr>

// result => "a"

解答

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

解説

処理の流れ

  • <T extends any[]>

    Tを配列のみ受け取るように制約。

  • T extends [infer U, ...any[]] ? ...

    条件分岐(T[infer U, ...any[]]の形だったら...)で評価を行う。

  • [infer U, ...any[]]

    • infer U

      要素の最初の要素の型推論を行う。

    • ...any[]

      配列の残りの要素を表す。

  • ... ? U : never

    最初の要素があればU、なければneverを返す。

Conditional Types(型の条件分岐)とは...

  • 条件によって型を決めることができる。

  • 三項演算子で記述する。

  • extendsの記述が必要

T extends U ? X : Y;
// trueならX、falseならY

type IsString<T> = T extends string ? true : false;
type IsString<"a"> // => true;

inferとは…

  • inferは型推論を行う(inferの直訳は推論)。

    「型の中から必要な部分を取り出して名前をつける」ための道具。

  • extendsの右辺にのみ記述が可能。

なぜ型推論をして、具体的な値("a"や0)を抽出できるのか?

TypeSciptは型推論の際に、可能な限り具体的な型推論を行うから。

["a", "b", "c"]の配列の最初の要素は明確に`"a"`という文字列
→ 型として`string`よりも具体的な`"a"`という文字リテラル型が推論される。

スプレッド構文(…)とは…

  • 省略して書いてるイメージ

  • [infer U, ...any[]]の部分は、「最初の要素の型をUとして推論し、残りは何でも良い」という意味合いを持つ。

  • 下記のような使い方もできる。

const list = ["Japan", "China", "Korea"]
const NewList = [...list, "France"]

// NewList => ["Japan", "China", "Korea", "France"]

参考記事

Conditional Types

infer

スプレッド構文


yuto99999の画像
yuto99999

yuto99999 has shared 41 reflections. Discover new insights this platform.