パラメータとしてタイプスクリプト関数を受信すると、パラメータの数が少なくなります.


疑問点


完全なコード:
TypeScript (forked)
タイプスクリプトで関数をパラメータとして受信する場合、パラメータが1つと2つある場合.
function inFunc1(a:number, b:number) {
	return a + b;
}

function inFunc2(a:number) {
	return a + 99;
}

function inFunc3() {
  return 765;
}

function wrapper(f: (arg1: number, arg2: number) => number) {
  return (a1: number, a2: number) => {
    return f(a1, a2);
  };
}
  let aa = wrapper(inFunc1)(1, 2);
  let bb = wrapper(inFunc2)(3, 4);
  let cc = wrapper(inFunc3)(5, 6);
  console.log(aa, bb, cc); // {aa: 3, bb: 102, cc: 765}
上のコードではタイプスクリプトエラーは発生しません.どうしてこんなことになったの?任意の減少因子の関数が受け入れられるようだ.
wrapper((a, b) => 3)(5, 6);
上のように書いてもいいです.
wrapper((a:string) => 3)(5, 6);
しかし、上記のようにタイプが違うわけにはいきません.しかし
wrapper((a, b, c: number) => 3)(5, 6);
以上のように,因子が2つを超えてもだめである.
fをコンソールに撮る
function wrapper(f: (arg1: number, arg2: number) => number) {
  return (a1: number, a2: number) => {
    console.log(f); // 뭐가 나올까?
    return f(a1, a2);
  };
}
以下に示す.
return f(a1, a2);セクションでは、デフォルトのファクタが自動的に切断されます.
なぜタイプスクリプトがこの状況をエラーとして位置づけていないのですか?

答え


バニラFAQで見つけました.
https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters
... これは予想される理想的な動作です.「第一に、下塗りを参照してください」残りのパラメータは安全に無視されます.
例:
let items = [1, 2, 3];
items.forEach(arg => console.log(arg));
パッと見て?実際、これは間違いかもしれません.実行時、forEachは本来3つのパラメータ(value, index, array)を受け入れるが、通常コールバックはvalueとindexのみを使用する.これは非常に一般的なJavaScriptモードで、使用しないパラメータを宣言するのは面倒かもしれません.
しかし、forEachはオプションと表記されていますか?forEach(callback: (element?: T, index?: number, array?: T[]))これは外来コールバックパラメータを意味するものではありません!関数記号は常に呼び出し元の角度から読み出されます.forEachがパラメータとして宣言された場合、forEachは0個のパラメータによって呼び出され得ることを示す.
// Invoke the provided function with 0 or 1 argument
function maybeCallWithArg(callback: (x?: number) => void) {
    if (Math.random() > 0.5) {
        callback();
    } else {
        callback(42);
    }
}
forEachは、常にコールバックに3つのパラメータをすべて提供します.indexundefined-はずっとあります.見張りパイオニアじゃない!
現在のタイプのスクリプトでは、コールバックパラメータが存在する必要があることを示すことはできません.

結論として,従来の基準ではvalue,index,arrayともに含まれるコールバック関数を受け入れるべきであったが,このような必要はなく,()⇒console.log()等で圧縮できる便利な設計であった.
だからforeachを直接実現すれば、なぜ便利なデザインなのかがわかります.
function myForEach<T>(
  arr: T[],
  callbackfn: (value: T, index: number, array: T[]) => unknown,
  thisArg?: any
) {
  for (let i = 0; i < arr.length; i++) {
    callbackfn.call(thisArg ? thisArg : this, arr[i], i, arr);
  }
}

const test = ["하나", "둘", "셋"];
// 아래 네 구문 모두 허용된다.
myForEach(test, () => {
  console.log("하이도모");
});

myForEach(test, (value) => {
  console.log("하이도모" + value);
});

myForEach(test, (value, i) => {
  console.log("하이도모" + value + i);
});

myForEach(test, (value, i, arr) => {
  console.log("하이도모", arr);
});