9

スペック活字体Array.prototype.map宣言

が...このよう

var new_array = arr.map(callback[, thisArg]) 

問題を使用する必要があります

活字体のためのいくつかのオーバーロードされた宣言を持っていますこれは非常に難しくなりますextend Array<T>。私はこの(lib.d.tsである) ...

map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; 

しかしlib.d.tsを見ることを期待する

はまた、これらの...

map<U>(this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U]; 

map<U>(this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U]; 

map<U>(this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U]; 

map<U>(this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U]; 
を持っています

異論

JavaScriptではメソッドのオーバーロードが許可されていないため、クラス実装のためのTypeScriptもどちらも実装されていませんTypeScriptが周囲の宣言のためにこれを許すべきだと考えてください。

質問

  1. なぜ活字体は、周囲の宣言のためにオーバーロードされた署名を許可していますか?
  2. Arrayを拡張するクラスのマップ実装をオーバーライドするにはどうすればよいですか?私はあまりにも... https://github.com/Microsoft/TypeScript/issues/13785

    ReadonlyArray<T>があるだけでマップのための単一の署名を、持っているGitHubの上でこれを提起しました

...

map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[]; 
+0

ここで最も重要なのは、IMOとは何かについて尋ねなかったのは興味深いことです:_purpose_。 *「なぜこれらすべてのオーバーロードシグネチャを最初に定義するのですか?」* - その答えは、TypeScriptには要素の有限数を持つ配列の型概念があります。たとえば、[[number 、number、number] 'は3要素のnumber []'です。これは_to_と_from_ 'number []'の両方に割り当て可能ですが、コンパイラの観点からはまったく同じではありません。また、これらはある種の文脈ではタプル型とも呼ばれ、必ずしも相互に代入可能なelem型を定義することはできません。 –

+0

@JohnWeisz私はn要素配列の概念を得ていますが、なぜこの概念は5要素配列で止まるのでしょうか?確かにnは無限になる可能性がありますか? – series0ne

答えて

2

(1)アンビエント宣言でシグネチャのオーバーロードを許可されない場合、どのように異なるシグネチャを取得しますかsのネイティブjs関数/メソッド?
lib.d.tsには、ネイティブjsオブジェクトの動作を反映したオーバーロードが多数あります。

(2)宣言されている可能性のあるすべてのシグネチャをカバーしていることをコンパイラに伝える必要があります。

class A<T> extends Array<T> { 
    map<U>(this: Array<U>, ...args: any[]); 
    map<U>(this: Array<T>, callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] { 
     return []; 
    } 
} 

最初の過負荷署名はあなたが気にしたくないものの世話をする:あなたのような何かを行うことができますあなたの場合は

1

あなたの質問は、TypeScriptのさまざまな側面に触れています。私はそれらを個別に扱い、すべて一緒に置くでしょう。

アレイ<T>

インタフェースは、活字体で二重の目的を果たす:

  1. 彼らはあなたが実装するために、他の(まだ存在しない)クラスに対して「真」のインターフェイスを作成することができます。それを実装するときは、インターフェースがすべてのメンバーが利用可能であることを保証するので、それをentiriely実装する必要があります。
  2. のインターフェイスを定義することができます。既に存在するのは JavaScriptタイプです。これは非常に多くの既存のライブラリの1つを使用したいが、静的な型指定の利点がある場合に非常に便利です。これらのインターフェイスは、通常.d.tsファイル(およびlib.d.tsファイルには基本的なJavaScriptタイプが含まれています)で定義されています。これらのインターフェースは既存のタイプに合わせて作られており、通常は実装するためのものではありません。しかし、あなたは望むことができますが、すべてのメンバーを実装する必要があります。

Array<T>インターフェイスは2番目の種類のインターフェイスなので、実装することはできません。機能

thisパラメータ関数定義でthis:パラメータを使用して、引数を渡すことができるという意味では本当のパラメータではありません。ファンクション本体の値がthisであると予想されるタイプを指定することができます。これを指定しないと、thisanyのタイプになります。これはしばしばあまり役に立ちません。活字体で

オーバーロード

関数/メソッド、関数および方法は、それらがJavaやC#などの言語でオーバーロードされている意味でオーバーロードされていません。一度より頻繁に実装することはできませんが、バリアントタイプを返す関数やバリアントパラメーターを使用する関数の静的型指定を可能にする代替シグネチャを定義することができます。特に.d.tsの定義ファイルでは、既存のライブラリはJavaScriptの弱い型付けを使用して値を返したり、さまざまな型のパラメータを期待しているので、これは便利でしばしば必要です。それはあなたの反対を間違ってしまいます。これらのJavaScriptコンストラクトに対応するには、関数のオーバーロードが必要です。 JavaScript配列で

タプル

あなたがそのスロットのそれぞれに複数種類の値を割り当てることができます。 TypeScript配列定義では、という1つのタイプを指定します。これはコンパイラによって適用されます。ギャップを埋めるために、タプルを定義することができます。 [number, string, string]のような型は、JavaScript配列any[]に変換され、TypeScriptは静的型付けを強制することができます。

アレイ法は、あなたがArray<T>に反対オブジェクトをオーバーロード概要

が配列の実際の[T, T]である場合には静的に型付けさthisパラメータを導入し、[T, T, T][T, T, T, T][T, T, T, T, T]。配列が複数の方法を提供することを意味するものではありません。mapこれは同じ方法ですが、一部の特定の配列型ではオーバーロードされます。それはlib.d.tsで提供されており、あなた自身によって実装されるようには設計されていません。基底のクラスを拡張することができます(既にインタフェースがなくても既に存在しています)が、オーバーロードはあなたに害を与えません(少なくともこの場合はthisのパラメータしか提供しません)。

+1

'Array'は実際にあなたが拡張できるクラスです。この答えを投稿する前にチェックしておいたはずのものです。あなたの長い説明はすべて、彼が尋ねたこととどのように彼がそれに尋ねたかに基づいて、おそらくOPに知られています。 –

+0

@NitzanTomer:私は(https://github.com/Microsoft/TypeScript/blob/master/lib/lib.d.ts - 「インターフェイスアレイ {」)を検索しました。あなたは、より良いOPを知っているようです私がやります。 – Sefe

+0

'interface Array 'の後に、コンストラクタを定義する 'interface ArrayConstructor'があり、次に' Array'をクラスにする 'declare const Array:ArrayConstructor'があります。 –