これはlib.d.ts
のbind
の定義です:
bind(thisArg: any, ...argArray: any[]): any;
見ての通り、anyを返します!つまり、関数のbind
を呼び出すと、元の関数のシグネチャの型安全性が完全に失われます。
たとえば、次のようにコンパイルします:
function twoParams(a:number,b:number) {
return a + b;
}
let curryOne = twoParams.bind(null,123);
curryOne(456); // Okay but is not type checked!
curryOne('456'); // Allowed because it wasn't type checked!
それを書くためのよりよい方法は、明示的な型アノテーションを持つ単純なアロー関数です。
function twoParams(a:number,b:number) {
return a + b;
}
let curryOne = (x:number)=>twoParams(123,x);
curryOne(456); // Okay and type checked!
curryOne('456'); // Error!
しかし、あなたがカリー化された関数を必要とする場合は、それにはより良いパターンがあります。
bind
の別の一般的な使い方は、クラス関数を渡すときにthis
の正しい値を保証するためにbind
を使うことです。それはやらないでください!
次の例は、bind
を使うとパラメータの型安全性を失うことを示しています:
class Adder {
constructor(public a: string) { }
add(b: string): string {
return this.a + b;
}
}
function useAdd(add: (x: number) => number) {
return add(456);
}
let adder = new Adder('mary had a little 🐑');
useAdd(adder.add.bind(adder)); // No compile error!
useAdd((x) => adder.add(x)); // Error: number is not assignable to string
もしあなたが他に渡すことを期待しているクラスメンバ関数を持つ場合は、そもそもアロー関数を使います。例えば、上記と同じAdder
クラスを以下に示します:
class Adder {
constructor(public a: string) { }
// This function is now safe to pass around
add = (b: string): string => {
return this.a + b;
}
}
もう1つの方法は、バインドする変数の型を手動で指定することです。
const add: typeof adder.add = adder.add.bind(adder);