MofuMofu2 / typescript-sandbox

MIT License
0 stars 0 forks source link

feature: #51 ジェネリック型の利用 #52

Closed MofuMofu2 closed 1 year ago

MofuMofu2 commented 1 year ago

close #51 最初ジェネリック型の定義を忘れていたけどCopilotに説明してもらった。エラーを説明してもらえるのめっちゃ便利。 なんか頭が悪くなりそう…。

MofuMofu2 commented 1 year ago

コードを確認しました。ジェネリックの利用に関して、非常に良い実装をされています。

ポジティブな点:

  1. ジェネリックの正確な利用: 関数getLastElementはジェネリック<T>を利用しており、任意の型の配列を受け取り、その型の最後の要素を返すことができます。

  2. 型推論: pokemon配列をgetLastElement関数に渡すと、TypeScriptの型推論が動作して、関数がstring型の値を返すことを自動的に認識します。

改善点:

このコードの文脈において、特に指摘するような改善点は見当たりません。ただし、関数が空の配列を受け取る場合、undefinedを返す可能性があることに注意が必要です。これを防ぐためのエラーハンドリングや対応策を考えることができます。

全体として、ジェネリックの基本的な利用方法を非常によく理解されていると感じます。良い実装です!


確かにundefinedを返すので、ケアはした方がいいかも。

MofuMofu2 commented 1 year ago

次のようなコードを投げてみた。0以上にする必要はあるが、他にも指摘されるだろうか

function getLastElement<T>(arr: Array<T>) {
  return arr.length > 1 ? arr[arr.length - 1] : "Array is undefined.";
}

const pokemon = ["ピチュー", "ピカチュウ", "ライチュウ"];

console.log(getLastElement(pokemon));

コードの更新を確認しました。エラーハンドリングのための条件を追加しているのがわかります。しかしながら、少し修正が必要です。

問題点:

改善提案:

function getLastElement<T>(arr: Array<T>): T | null {
  return arr.length > 0 ? arr[arr.length - 1] : null;
}

const pokemon = ["ピチュー", "ピカチュウ", "ライチュウ"];
console.log(getLastElement(pokemon));

上記のコードでは、配列が空の場合にnullを返すようにしています。これによって、関数の返り値がジェネリックTnullのどちらかであることが保証されます。

MofuMofu2 commented 1 year ago

これはジェネリックの利用としては最適ではありません について解説してください。

もちろん、詳しく説明いたします。

ジェネリックは、型の柔軟性を保ちつつ、コードの再利用性を高めるためのTypeScriptの機能です。ジェネリックを使用する主な目的は、関数、クラス、インターフェイスなどがさまざまな型で動作することを保証しつつ、型の安全性を保持することです。

当初の関数実装において以下の部分が問題です:

return arr.length > 1 ? arr[arr.length - 1] : "Array is undefined.";

この関数は、次の2つの問題点を持っています:

  1. 返り値の型の不一致: 関数の定義にジェネリックTを使用しているにもかかわらず、実際の返り値はTまたはstringとなります。これは、関数がどんな型の配列を受け取っても、エラーの際には文字列を返すという動作を意味します。例えば、この関数がnumber[]型の配列を受け取ると期待している場合、エラーメッセージの文字列を返すことは予期しない動作となり、型の安全性が損なわれます。

  2. エラーメッセージの内容: "Array is undefined."というメッセージは、実際の問題を正確に反映していません。配列自体がundefinedではなく、空であるというのが正しい状況です。

ジェネリックを「最適に」使用するというのは、ジェネリックの型変数(この場合はT)と一致する型、またはその型と予期できる関連性を持つ型を返すことを意味します。返り値が予期しない型(この場合はstring)になると、関数の使用者は混乱する可能性がありますし、予期しないバグの原因ともなり得ます。

したがって、ジェネリック関数を設計する際は、関数の返り値がジェネリックの型変数と一貫性を持つようにすることが推奨されます。


推論させるんだから、それを壊さないようにするのが重要。ない = nullかundefinedなんだからそれを推論させろということ。

MofuMofu2 commented 1 year ago

ChatGPTの指摘の方が真っ当なので、提案してもらったコードにした。そして、空であることを返すべきなのでnullで返すようにした。