Skip to content

Latest commit

 

History

History
74 lines (56 loc) · 2.03 KB

bind.md

File metadata and controls

74 lines (56 loc) · 2.03 KB

Bind is Harmful

This is the definition of bind in lib.d.ts:

bind(thisArg: any, ...argArray: any[]): any;

As you can see it returns any! That means that calling bind on a function will cause you to completely lose any type safety of the original function signature.

For example the following compiles:

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!

A better way to write it would be with a simple arrow function with an explicit type annotation:

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!

But if you expect a curried function there is a better pattern for that.

Class Members

Another common use is to use bind to ensure the correct value of this when passing around class functions. Don't do that!

The following demonstrates the fact that you lose parameter type safety if you use 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

If you have a class member function that you expect to pass around, use an arrow function in the first place e.g one would write the same Adder class as:

class Adder {
    constructor(public a: string) { }

    // This function is now safe to pass around
    add = (b: string): string => {
        return this.a + b;
    }
}

Another alternative is to manually specify the type of the variable you are binding e.g.

const add: typeof adder.add = adder.add.bind(adder);