The issue lies in how TypeScript and JSDoc interact. Specifically, in JSDoc, expressing that this method should be a specific object like foo can be tricky, but it’s possible. To fix this issue and achieve proper IntelliSense and type inference, explicitly define the @this annotation using the exact object type.
Here’s how you can fix your code:
Solution
/**
* @typedef {Object} Foo
* @property {string[]} bar
* @property {Baz} baz
*/
/**
* @typedef {Object} Baz
* @property {function(this: Foo, string): number} bing
*/
const foo = {
/** @type {string[]} */
bar: [],
/** @type {Baz} */
baz: {
/**
* @param {string} x
* @returns {number}
* @this {Foo}
*/
bing(x) {
this.bar.push(x);
return 42;
}
}
};
// methods are invoked like so:
const method = "bing";
foo.baz[method].call(foo, "blah");
Explanation:
@typedef
for Foo
: This defines the type of the foo
object. It specifies that foo
has a bar
property (an array of strings) and a baz
property of type Baz
.@typedef
for Baz
: This describes the shape of the baz
property, including the bing
method, which is explicitly annotated to use this: Foo
.@this {Foo}
in bing
: This ensures that the this
context of the bing
method is typed as Foo
.If you were to use @type {typeof foo}
, IntelliSense often struggles because typeof foo
cannot be fully resolved in the JSDoc context. Explicitly defining Foo
and Baz
gives TypeScript the clarity it needs