きり丸の技術日記

技術検証したり、資格等をここに残していきます。

TypeScriptでPythonのキーワード引数みたいな挙動をさせる(ROROパターン)

TypeScriptを書いていて、Pythonでいうキーワード引数(名前付き引数)のような挙動をしたいとTwitterに呟いたところ、【公式】皮しばきさん、suinさんに反応していただけました。

その中でsuinさんに教えていただいたデザインパターンのROROパターン(Receive an object, return an object)が自分の期待した動きをしたので、ブログにまとめます。

twitter.com

なお、今回の記事はsuinさんに紹介していただいたmediumの記事をローカルで検証した結果ですので、より詳細なメリットは原文を読んだ方が理解できます。

環境

  • TypeScript
    • 不明
      • PlayWrightのv1.15.0に含まれるバージョン
    • v4.4.3
      • codesandboxで検証したバージョン

ゴール

  • TypeScriptでもPythonのキーワード引数(名前付き引数)に似た挙動をさせる

そもそも、キーワード引数とは

Pythonにはキーワード引数という機能があります。この機能はメソッド呼び出しでパラメータ前に識別できるパラメータ名を一緒に渡すことで、順番に依存せず、メソッドにパラメータを渡せる機能です。

# メソッドの定義
def send_mail(mail_from='example@co.jp', mail_to='example@co.jp', text='テストメール', name='運営'):

# メソッドの呼び出し
send_mail(mail_to='hogehoge@co.jp')
# mail_fromは「exmaple@co.jp」 
# mail_toは「hogehoge@co.jp」
# textは「テストメール」
# nameは「運営」
# のパラメータで渡される

メリットとしては、いくつかあります。

  • 必要な箇所にのみパラメータを渡すことができる
  • パラメータを増やしても呼び出し元に一切影響を与えない
  • Javaでいうオーバーロードせずに表現できる
    • シンプルに表現できる

なお、順番で識別されるパラメータのことをPythonでは位置引数と呼びます。

ROROパターン(Receive an object, return an object)とは

メソッド呼び出し時にobjectでパラメータを渡し、返却値もobjectで返却するデザインパターンです。なお、今回私が感銘を受けたのはメソッド呼び出し時の挙動ですので、返却値の話はしません。

// 既存の呼び出し
send_mail('example@co.jp', 'example@co.jp', 'テストメール', '運営');
// ROROパターンの呼び出し
send_mail({ mail_from='example@co.jp', mail_to='example@co.jp', text='テストメール', name='運営'});
// 既存の呼び出し元
function send_mail(mail_from, mail_to, text, name) {}
// ROROパターンの呼び出し元
function send_mail({ mail_from, mail_to, text, name }) {}

必須チェックと不要な変数チェック

現状のままでは、キーワード引数のメリットを享受できません。型を用意しましょう。今回はメール送信者の名前であるnameを非必須とします。

// メソッドの型
type EMailType = {
  mail_from: string; // メール送信元
  mail_to: string; // メール送信先
  text: string; // 本文
  name?: string; // メール送信者の名前
};
// 型を付与する
function send_mail({ mail_from, mail_to, text }: EMailType) {}

この状態で必須項目が足りない、または定義していない変数名を指定した場合、エラーを出力してくれるので間違いに気付きやすくなります。

f:id:nainaistar:20210924001351p:plain

初期値の設定

非必須項目に初期値を与えられます。

function send_mail({ 
  mail_from, 
  mail_to, 
  text, 
  name = '公式'
}) {}
// メソッドの呼び出し
send_mail({ mail_from: "a", mail_to: "b", text: "c" });
// nameには初期値の「公式」

send_mail({ mail_from: "a", mail_to: "b", text: "c", name: "d" });
// nameにはパラメータで渡した「d」

ソースコード

終わりに

objectでメソッドに渡して、メソッドでobjectを展開できるとは知りませんでした。

Mediumの記事では今回紹介しなかったROROパターンでのメリット・デメリットが紹介されています。今回、私の記事で紹介していないのは、ユースケースが分からなかったものと、再現ができなかったからです。

私の希望するPythonのキーワード引数みたいな挙動をTypeScriptでもできる、という最低条件は確認しましたので、ブログに残しました。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考情報

f:id:nainaistar:20210924001501p:plain