0
0

Type Challenges 中級編15: Reverse, Flip Arguments, FlattenDepth

はじめに

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

1. Reverse

この課題では、配列を逆順にする型を実装します。これはJavaScriptの Array.reverse の型版です。

type A = Reverse<['a', 'b']>; // ['b', 'a']
type B = Reverse<['a', 'b', 'c']>; // ['c', 'b', 'a']

私の回答

type Reverse<T extends Array<unknown>, U extends Array<unknown> = []> = 
  T extends [infer F, ...infer Rest] ? Reverse<Rest, [F, ...U]> : U;

解き方

  • Reverse 型は、ジェネリック型 T が配列であることを前提とし、再帰的に先頭要素 F を取り出して残りの要素 Rest を逆順にします。
  • 基本的な考え方は、配列の先頭要素を新しい配列 U の先頭に追加していくことです。

このようにして、配列を逆順にする新しい配列型を作成することができます。

再帰を使用して新しく配列を作ってしまえば問題ないですね!

2. Flip Arguments

この課題では、関数の引数の順序を逆にする型を実装します。これはLodashの _.flip の型版です。

type Flipped = FlipArguments<(arg0: string, arg1: number, arg2: boolean) => void>;
// (arg0: boolean, arg1: number, arg2: string) => void

私の回答

type Reverse<T extends Array<unknown>, U extends Array<unknown> = []> = 
  T extends [infer F, ...infer Rest] ? Reverse<Rest, [F, ...U]> : U;

type FlipArguments<T> = 
  T extends (...args: infer ARGS) => infer R ? (...args: Reverse<ARGS>) => R : never;

解き方

  • FlipArguments 型は、関数型 T が引数 ARGS と戻り値 R を持つ場合に、引数の順序を逆にした新しい関数型を返します。
  • まず、Reverse 型を使って引数 ARGS の順序を逆にし、その結果を新しい関数型として返します。

このようにして、関数の引数の順序を逆にする型を作成することができます。

関数の引数を推定して1問前のReverseを使えば簡単ですね、

3. FlattenDepth

この課題では、配列を指定された深さ depth まで再帰的にフラット化する型を実装します。深さが指定されていない場合は1回フラット化します。

type A = FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2>; // [1, 2, 3, 4, [5]]. flattern 2 times
type B = FlattenDepth<[1, 2, [3, 4], [[[5]]]]>; // [1, 2, 3, 4, [[5]]]. Depth defaults to be 1

(答えを見ました、情けない、、)

type FlattenDepth<
  T extends any[],
  S extends number = 1,
  U extends any[] = []
> = U['length'] extends S
  ? T
  : T extends [infer F, ...infer R]
  ? F extends any[]
    ? [...FlattenDepth<F, S, [...U, 1]>, ...FlattenDepth<R, S, U>]
    : [F, ...FlattenDepth<R, S, U>]
  : T;

解き方

  • U は再帰的にフラット化するためのカウンタとして使用しているようです
  • U['length']S に達するまで、配列の各要素をチェックし、ネストされた配列の場合は再帰的にフラット化しているようです、思いつかないだろこんなの、、

いや難しすぎる!!〇〇回繰り返す、とか難しい、、、

まとめ

これらの課題を通じて、TypeScriptの型システムに対する理解が深まり、複雑な型操作のスキルが向上します。特に、タプルや配列の操作、オブジェクト型のプロパティの操作に関する知識を強化できます。ぜひ、これらの課題に挑戦して、型の理解を深めてください。

参考記事

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