typescript

type-challenges 16日目: 12-Chainable Options

#typescript#type-challenges

問題 & 解答

https://github.com/type-challenges/type-challenges/blob/main/questions/00012-medium-chainable-options/README.md

option(key, value)を任意の数チェインして、最終的な結果をget()で呼び出すような 2 つの関数を提供する型を定義する。

type Chainable<Options = {}> = {
  option<K extends string, V>(
    key: K,
    value: V
  ): Chainable<Options & { [S in K]: V }>;
  get(): Options;
};

全然わからなくて答えをみたので、解析していく。まず、単純にoptionメソッドを持つオブジェクトを考える。

このメソッドの要件は

  1. 引数はkeyvalueで、keystringvalueに任意の型を受ける
  2. 戻り値はここまで追加された option(オブジェクト)と、今回メソッドに渡された key と value で生成された option(オブジェクト)が合わさったもの。
// ここまでに定義されたOptionをチェーンする。何もOptionがなければ`{}`が初期値として設定される
type Chainable<Options = {}> = {
  option<K extends string, V>(
    key: K,
    value: V
  ): Chainable<Options & { [S in K]: V }>;
};

declare const base: Chainable; // Chainable<{}>

// Optionsは初期値`{}`
// Chainable<{} & { "require": boolean }>
// Chainable<{ require: boolean }>
const requireOptionAdded = base.option("require", false);

// optionで返されているOptionsは`{ require: boolean }`
// Chainable<{ require: boolean } & { old: boolean }>
// Chainable<{ require: boolean,  old: boolean; }>
const oldOptionAdded = requireOptionAdded.option("old", true);

あとは現在保持している Options を返すようにgetを実装する。

type Chainable<Options = {}> = {
  option<K extends string, V>(key: K, value: V): Chainable<Options & { [S in K]: V }>
+  get(): Options;
}

調べたこと

アンビエント宣言(declare

JavaScript コードを生成せずに、型推論のためだけの情報を渡すのに使用する。

declare;
a: number;

感想

再帰とはまた違った形式だけれど、地味に汎用性の高い型定義だと思うので覚えておこう


Buy Me A Coffeeikuma-tにお恵みを!