Bind an object to this
in all methods in a function, object, or array. A simple, single-dependency (only for TypeScript types) alternative to deep-bind.
- Binds the root function and all own, enumerable property functions including property accessors
- Compatible with functions, arrays, objects, custom classes, and array-likes
- Binds the
this
value and optionally, additional arguments just likefunc.bind()
- Copies objects and enumerable properties deeply
- Preserves and copies prototypes for all types
- New in
v2.1.0
: Strict TypeScript type definitions
npm install bind-deep --save
Returns: Function
| Object
| Array
- The function or object passed as object
but with
itself and all methods bound to thisArg
Parameter | Type | Description |
---|---|---|
object | Function | Object | Array |
Function or object to bind itself and all of its methods |
thisArg | Object |
The value bound to this for each bound function and method when called |
[...args] | any |
Arguments provided to the bound function when the bound function is invoked |
// Require bind-deep
const bindDeep = require("bind-deep");
// Original object and function
// Could also be an actual object
const func = function() {
// Use `this`
};
func.method = function() {
// Use `this` again
};
const obj = {
method() {
// Use `this`
}
};
// Deeply bound object and function
// `thisArg` will be what every function and method will see as `this`
const boundObj = bindDeep(obj, thisArg);
// => {method: [Function: bound]}
const boundFunc = bindDeep(func, thisArg);
// => {[Function: bound] method: [Function: bound]}
All types inferred or annotated are preserved from the original functions and objects. The type definitions are incredibly strong deep types as the only negative side-effects are:
- If bound arguments are added, the arguments in call signatures are renamed by their bound position.
- If more than around 39 bound arguments are added, TypeScript will error
Type instantiation is excessively deep and possibly infinite.
- If you somehow do this, slap on an
as any
or your manually created type
- If you somehow do this, slap on an
An in-depth explanation is commented inside of index.d.ts
and below with example code.
// Import bind-deep
import bindDeep from "bind-deep";
interface OriginalThis {
discriminator: string;
}
// Original function
const myFunction = function (this: OriginalThis, arg1: string, arg2: number) {
return this;
};
myFunction.method = function (this: OriginalThis, arg1: string) {
return this;
};
myFunction.primitive = "string";
// `thisArg` value
const newThis = { newThis: "that's me!"};
// Deeply bound functions
const boundFunction = bindDeep(myFunction, newThis);
const boundFunctionWithArgs = bindDeep(myFunction, newThis, "add arg1 for each function");
/*
Root call signature: `(arg1: string, arg2: number) => OriginalThis`
- `this` argument type omitted from the original call signature as it is now bound
- All other argument types and names are preserved
- Returns `newThis` as `OriginalThis` due to the return value inferred by TypeScript
*/
boundFunction("arg1", 10); // returns `newThis`
/*
Root call signature when passing an argument: `((args_0: number) => OriginalThis)`
- Similar explanation to the root call signature
- `arg1` argument type omitted from the original call signature as it is now bound
- `arg2` is represented as `args_0` with the number type preserved
- This unfortunate renaming only occurs when binding arguments
*/
boundFunctionWithArgs(10); // returns `newThis`
/*
Method call signature: `(method) method(arg1: string): OriginalThis`
*/
boundFunction.method("arg1"); // returns `newThis`
/*
Method call signature when passing an argument: `(method) method(): OriginalThis`
*/
boundFunctionWithArgs.method(); // returns `newThis`
/*
Primitive property type: `primitive: string`
*/
const myString: string = boundFunction.primitive; // still "string", typings preserved
Copyright Evelyn Hathaway, MIT License