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の関数の引数optionalになりがち問題

読者の問題提起と解決策の提案

TypeScriptで関数を定義する時、引数をオプショナル(optional)にすることが多いですよね。便利な機能ですが、場合によっては予期しない動作を引き起こすことがあります。この記事では、この問題を解決する方法を具体例を通じて紹介します。

概要

関数の引数をオプショナルにする問題

TypeScriptでは、関数の引数をオプショナルにできます。しかし、これによって関数が予期しない動作をしたり、不正な引数が渡されたりすることがあります。

使用技術

  • TypeScript

具体例と詳細説明

例1: 単純なSMS送信関数

まず、単純なSMS送信関数を見てみましょう。

const greatToSms = ({ me, to, toSms, text }: { me: string; to: string; toSms: PhoneNumber; text: string }) => {
    sendToSms({ to: toSms, text: `Hi ${to}, ${me} says: ${text}` })
}

const sendToSms = ({ to, text }: { to: string; text: string }) => {
  console.log(`Sending SMS to ${to} with text: ${text}`)
}

この関数は正しく動作しますが、仕様変更に対応する必要が出てくることがあります。

例2: SMSまたはEmail送信関数

次に、SMSだけでなくEmailにも対応するように仕様変更があったとしましょう。

const greatToSmsOrEmail = ({
  me,
  to,
  sms,
  email,
  text,
}: { me: string; to: string; sms?: PhoneNumber; email?: Email; text: string }) => {
  if (sms) {
    sendToSms({ to: sms, text: `Hi ${to}, ${me} says: ${text}` })
  }
  if (email) {
    sendToEmail({ to: email, text: `Hi ${to}, ${me} says: ${text}` })
  }
}

この実装でも動作しますが、予期しない動作や不正な引数が発生する可能性があります。

実際のプロダクトでは実装が楽だからといって、このように書かれることが多いですが、かなり危険です。筆者は実務で、このコードのようにsmsemailが両方nullになってしまい、想定された動作をせず機能が動かないというケースを見てきました。

解決方法

以下のコードでは、引数をより厳密に定義しています。

const greatToSmsOrEmail = ({
  me,
  to,
  sms,
  email,
  text,
}: { me: string; to: string; text: string } & ({ sms: PhoneNumber; email?: never } | { email: Email; sms?: never })) => {
  if (sms) {
    sendToSms({ to: sms, text: `Hi ${to}, ${me} says: ${text}` })
  }
  if (email) {
    sendToEmail({ to: email, text: `Hi ${to}, ${me} says: ${text}` })
  }
}

この方法により、関数の引数が厳密に管理され、予期しない動作を防ぐことができます。

このように実装することで、以下のような実装ミスが発生した場合でも、TypeScriptの型エラーで防ぐことができます。

if (sms) {
  sendToSms({ to: sms, text: `Hi ${to}, ${me} says: ${text}` })
}
if (email) {
  sendToEmail({ to: sms, text: `Hi ${to}, ${me} says: ${text}` }) // 型エラーが発生
}

メリット・デメリット

メリット

  • 厳密な型定義により、予期しない動作を防止
  • 不正な引数の代入を防ぐ

デメリット

  • コードが少し複雑になる

総括と結論

TypeScriptの関数において引数をオプショナルにすることは便利ですが、仕様変更や予期しない動作を防ぐために、引数を厳密に定義する方法も検討する価値があります。型定義をしっかり行いましょう!

参考記事

この記事を通して、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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?