Bind is Bad

これはlib.d.tsbindの定義です:

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);

最終更新