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