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?

【TypeScript】type-challenges 初級編 898・Includes 解説

Last updated at Posted at 2024-12-11

お題

タプル型TUが含まれているか判定する型Includesを実装します。JavaScriptのArray.include関数を型システムに実装します。

やりたいこと

type test1 = Includes<["Kars", "Esidisi", "Wamuu"], "Kars">; // true
type test2 = Includes<["Kars", "Esidisi", "Wamuu"], "Dio">; // fasle
type test3 = Includes<[{}], { a: "A" }>; // false
type test4 = Includes<[boolean, 2, 3, 5, 7], false>; //false

解答

type Includes<T extends readonly any[], U> = {
  [P in T[number]: true;
}[U] extends true
  ? true
  : false;

解説

処理の流れ

  • { [P in T[number]: true; }
    T[number]で返されたユニオン型を使って、オブジェクトを作成する。
example.ts
// Tが["Kars", "Esidisi", "Wamuu"]場合
// ["Kars", "Esidisi", "Wamuu"][number] =>  "Kars" | "Esidisi" | "Wamuu"
{
  "kars": true,
  "Esidisi": true,
  "Wamuu": true,
}
  • { [P in T[number]: true; }[U]
    インデックスアクセス型の利用

  • { [P in T[number]: true; }[U] extend true ? true : false
    インデックスアクセス型でプロパティの型がtrueかどうかで条件分岐を行う。

// Includes<["Kars", "Esidisi", "Wamuu"], "Kars">; の場合

{"kars": true, "Esidisi": true, "Wamuu": true,}["kars"] //  => true

なぜ下記のコードでは期待した結果が得られないのか?

type TestInclude<T extends readonly any[], U> = U extends T[number]
  ? true
  : false;

こちらのコードでは、Tにユニオン型やオブジェクトが含まれる場合、期待した結果を得られません。

type test5 = Includes<[{}], { a: "A" }>; // => falseのはずがtrue
type test6 = Includes<[true, 2, 3, 5, 6, 7], boolean>; // falseのはずがtrue
type test7 = Includes<[1], 1 | 2>; // falseのはずがtrue

単純なextendsチェックの場合、ユニオン型では部分一致が、オブジェクトやboolean型ではサブタイプが許容される。そのため、期待した結果が得られない。

[number]とは...

インデックスアクセス型とは...

参考記事

今回の問題

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?