Yuzhe's Blog

yuzhes

0014 · First of Array

Posted at # TypeScript # TypeChallenge # TC-Easy
EN ·

0014 · First of Array

Challenge Link

Problem

Implement a generic First<T> that takes an array T and returns its first element’s type.

type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]

type head1 = First<arr1> // expected to be 'a'
type head2 = First<arr2> // expected to be 3

Solution

// Option 1: Conditional type approach
type First<T extends any[]> = T extends [] ? never : T[0]

// Option 2: Infer approach
type First<T extends readonly any[]> = T extends [infer F, ...infer R] ? F : never

Explanation

Naive Approach and Its Problem

The simplest idea is to just index the first element:

type First<T extends any[]> = T[0]

This works for non-empty arrays, but when T is an empty array [], T[0] resolves to undefined instead of never. The test cases expect never for empty arrays.

Option 1: Conditional Type Guard

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

We explicitly check if T is an empty array. If it is, return never; otherwise return T[0].

Step by step:

  1. T extends any[] — constrains T to be an array type
  2. T extends [] — checks if T is the empty tuple type
  3. If empty → never; otherwise → T[0] (the first element)

Option 2: The infer Keyword

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

This uses the infer keyword to pattern-match the tuple structure:

The infer keyword introduces a new type variable within a conditional type, letting TypeScript infer it from the matched structure.

TIP

readonly any[] is used instead of any[] so that the type works for both regular arrays and readonly tuples. A regular array is a subtype of a readonly array, so readonly any[] is the more general constraint.

Key concepts:

中文解析

核心思路:

取数组第一个元素类型,看似简单,但需要处理空数组边界情况

// 方案一:条件类型判断
type First<T extends any[]> = T extends [] ? never : T[0]

// 方案二:infer 模式匹配(更优雅)
type First<T extends readonly any[]> = T extends [infer F, ...infer R] ? F : never

为什么不能直接用 T[0]

type First<T extends any[]> = T[0]  // ❌ 空数组时返回 undefined,而非 never

空元组 [] 的索引 [0] 类型是 undefined,但题目期望返回 never

方案一解析:

方案二解析(推荐):

考察知识点: