Programmingフルスタック開発者

TypeScriptにおける自動取得型(ReturnType、Parameters)のメカニズムについて説明してください。それらは何のために使用され、複雑な関数の型付け(例えば、オーバーロード)での動作のニュアンスは何ですか?

Hintsage AIアシスタントで面接を突破

回答。

ReturnType<T>Parameters<T> は、TypeScriptのユーティリティ型であり、関数の返り値の型(ReturnType)またはそのパラメータの型の配列(Parameters)を自動的に推論することができます。

これは、アプリケーション内のさまざまな部分間で型の一貫性を確保し、ジェネリックラッパーを実装するために特に便利です。

使用例:

function fn(a: number, b: string): boolean { return b.length > a; } type FnReturn = ReturnType<typeof fn>; // boolean type FnParams = Parameters<typeof fn>; // [number, string]

関数のオーバーロードに関するニュアンス: 関数のオーバーロードでは、ReturnTypeは最後のシグネチャのバージョンを定義し、Parametersはすべての可能なオーバーロードを定義します:

function overloaded(x: number): number; function overloaded(x: string): string; function overloaded(x: any): any { return x; } type OverRet = ReturnType<typeof overloaded>; // any type OverParams = Parameters<typeof overloaded>; // [any]

つまり、ユーティリティ型の型付けは常にすべてのオーバーロードを「見る」わけではないため、静的型付けが予測可能でなくなる場合があります。

トリッキーな質問。

ReturnTypeやParametersを使用して、カスタム関数のすべての可能なオーバーロードの型を、各オーバーロードを個別に定義することはできますか?

回答:

いいえ。ユーティリティ型のReturnTypeとParametersは、関数の「結合された」シグネチャのみを分析します — 実装のためにどのように記述されているかです。それぞれの個々のオーバーロードの型を取得することはできません — ただし、最終的に実装されたシグネチャの型だけです。

例:

type P = Parameters<typeof overloaded>; // [any]、ではなく [number]、[string]

テーマの細かい点を知らなかったための実際のエラーの例


物語

開発者たちは、ReturnType<T>を使用して返り値の型を型付けするためにaroundMethodというラッパーを作成しました。このラッパー関数は、オーバーロードされた関数に適用されました。結果: 型はあまりにも一般的(any)で、コンパイラは返り値の不一致を通知しませんでした。booleanとstringの間でバグがあることを遅れて発見しました。


物語

多数のAPI関数のパラメータをParameters<T>を通じて推論しようとした開発者は、メソッドのオーバーロードを考慮していませんでした。「誤った」型の問題が発生し、[string, number]の代わりに[any]が期待されました。ユニットテストは実装によってこのエラーをキャッチせず、実際のAPIユーザーはプロダクションでバグを受け取りました。


物語

JavaScriptからTypeScriptへの大規模なコード移行中に、開発者たちはすべて返り値の型をReturnTypeを通じて型付けしました。後で、実装がオーバーロードの宣言と大きく異なることを理解しました。そのため、誤った引数を持つシナリオが予期しないランタイム例外(例えば、TypeError: x is undefined)を引き起こしました。