ikuma-t.

検索

type-challenges 16日目: 12-Chainable Options

に公開

問題 & 解答

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;

感想

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

ikuma-t

ikuma-t

ABOUT

9割笑顔、1割 (´・ω・) なエンジニア