Open RedBeard0531 opened 1 year ago
Here is the actual code that caused me to run into this.
// This needs to be a separate const rather than an inline argument due to
// https://github.com/microsoft/TypeScript/issues/50467.
const bindingContext = {
isBoundCorrectly: true,
didChange(realm: Realm) {
assert(this.isBoundCorrectly);
console.log("in didChange()", realm.currentTransactionVersion);
},
beforeNotify(realm: Realm) {
assert(this.isBoundCorrectly);
console.log("in beforeNotify()", realm.currentTransactionVersion);
},
};
Helpers.setBindingContext(realm, bindingContext);
Interestingly, this is in a test of a native module generator to ensure that it is correctly invoking methods on objects with the correct this
context.
The definition for BindingContext
is generated as
export type BindingContext = {
didChange?: (r: Realm) => void;
beforeNotify?: (r: Realm) => void;
schemaDidChange?: (r: Realm) => void;
};
Suggestion
There are two issues with the type inference applied to object literals with methods in argument position:
this
type implicitly set to the inferred parameter type, rather than the actual type of the object literal (as they do in other contexts)The default behavior of not allowing unknown fields in object literals is useful in general because it detects typos in optional field names. However, it can be a problem if you want to add extra private(ish) data shared between methods on an object. I think that TS should not consider extra fields as "unknown" if they are used by methods on the object.
There are currently two workarounds (as shown in the code sample and playground link below): 1) pull the object literal out to a named const, or 2) make the function that accepts the object a template rather than giving it the exact interface type. These both have the downside that they completely turn off unknown field checking, so you can still get typos in optional parameters. I think that an ideal solution would still only permit "known" fields, it should just expand the definition of what fields are known.
🔍 Search Terms
I searched for "object literal methods" and poked around a bit, but didn't see anything like this. It is similar to "Contextual typing of methods and functions in object literals" in this PR, in that I think that change may have caused at least some of this.
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
I think your issue template has duplicate "Suggestion" sections...
📃 Motivating Example
Playground link
💻 Use Cases
This seems useful any time you want to pass an object literal with methods to a function.