Typescriptの引数としてリストとオブジェクトの両方で関数をオーバーライドする

2020-05-31 typescript parameters arguments overriding

誰かが最初のオーバーライドの署名が実装の署名と互換性がない理由を私に説明できますか?

標準のリスト引数と「名前付き」引数の両方をオブジェクトの形式で受け取る関数が必要です。

例えば、 react-queryuseQueryフックでそれが行われたのを見ました。私はそれらの型定義を見ました、そして彼らは私とほとんど同じようにやっているようです。

これが私の試みです:

interface Args {
  readonly a: string;
  readonly b?: boolean;
}

function foo(args: Args): number;
function foo(...args: [Args['a'], Args['b']?]): number;
function foo(a: string, b?: boolean): number { /* IMPLEMENTATION */ }

私は得る

This overload signature is not compatible with its implementation signature. ts(2394)

エラー。

そのオブジェクトを引数として取得すると、引数のリストとは異なるものになるため、 react-queryで実際にどのように機能するかはわかりません。

ただし、コードの検査から、同様の方法( types/index.d.ts参照)でuseQueryエクスポートのタイプ( *.d.tsファイル内)を定義しているようで、エクスポートされた実装は引数を分散しているようです。

src/useQuery.js

...
export function useQuery(...args) {
...

引数が配列型でない場合、TSでスプレッドを行うことができないため、この動作をどのようにシミュレートするかわかりません。

Answers

TypeScriptのオーバーロードリストの最後の関数は実装関数であり、関数呼び出しの可能なシグネチャとして認識されません。リストされたすべてのオーバーロードシグネチャの形状を実装で説明できる必要がありますが、TypeScriptは型チェック時にそれらのオーバーロードシグネチャ(および最終的な実装呼び出しではなく)のみを調べます。

以下はおそらくあなたが目指しているものです:

function foo(args: Args): number;
function foo(args: string, b?: boolean): number 
function foo(args: Args | string, b?: boolean): number { /* IMPLEMENTATION */ }

出典:

https://www.typescriptlang.org/docs/handbook/functions.html -そのページの最後の段落はこの動作を説明しています

TypeScript関数のオーバーロード -より詳細な説明

Related