0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

type-challenges 中級編3: Last of Array, Pop, Promise.all

はじめに type-challengesとは

GitHubのtype-challengesリポジトリは、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回は中級編から3つの問題に挑戦します。

1. Last of Array

配列 T を受け取り、その最後の要素の型を返す汎用的な Last<T> を実装してください。

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

type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1

私の回答

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

解き方

  • T extends [...infer Rest, infer U] という条件型を使い、配列 T の最後の要素 U を推定します。
  • 配列 T の最後の要素が U として推定される場合、その型 U を返します。
  • そうでない場合は never を返します。

inferとスプレッド構文を使えれば問題無く解けますね

もう一つの奇抜な型も思いついたので紹介します。

type Last<T extends unknown[]> = T extends [...infer U, unknown] ? T[U['length']] : never

実際のjsで書くと

arr[arr.length - 1]

と書いたような書き方ですね

キモいので上の方がいいですね

2. Pop

配列 T を受け取り、最後の要素を除いた配列を返す汎用的な Pop<T> を実装してください。

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

type re1 = Pop<arr1> // expected to be ['a', 'b', 'c']
type re2 = Pop<arr2> // expected to be [3, 2]

私の回答

type Pop<T extends any[]> = T extends [...infer U, unknown] ? U : []

解き方

  • T extends [...infer U, unknown] という条件型を使い、配列 T の最後の要素を除いた部分 U を推定します。
  • 配列 T の最後の要素を除いた部分が U として推定される場合、その型 U を返します。
  • そうでない場合は空配列 [] を返します。

Lastと一緒ですね。簡単。

3. Promise.all

Promise ライクなオブジェクトの配列を受け取る関数 PromiseAll に型を付けてください。戻り値は Promise<T> である必要があります。ここで、T は解決された結果の配列です。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

// expected to be `Promise<[number, 42, string]>`
const p = PromiseAll([promise1, promise2, promise3] as const)

私の回答

declare function PromiseAll<T extends readonly unknown[]>(values: T): Promise<{
  [K in keyof T]: Awaited<T[K]>;
}>;

解き方

  • 結果の型は Promise<...> で返す必要があります。
  • 配列 T の各要素 T[K] に対して、Awaited<T[K]> を使用して、そのPromiseが解決された型を取得します。

組込みの型Awaited 型を使用することで、Promiseオブジェクトの解決された型を簡単に取得できます。

まとめ

このように、TypeScriptの型システムを理解し、実際に型を実装することで、より安全で保守性の高いコードを書くことができます。ぜひこれらの課題を解いて、型力UPしてみてください。

参考記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?