TypeScript
TypeScript copied to clipboard
Type of "this" sometimes not respected for function declaration properties
Bug Report
🔎 Search Terms
- js this type
- js this function property
- function property this type
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about "Functions"
⏯ Playground Link
N/A - involves JS code which cant be emulated in playground at the moment
💻 Code
Below are some examples of the issue including the tsconfig.json and the code. The code comments describe what suggestions the intellisense provide, and here is what is expected, ie the types showing up on this as defined in the ts file:

The issue is below, where if the function assigns any property to this then the intellisense for this is limited to those assigned properties and ignores the defined type, e.g.:

🙁 Actual behavior
If the function assigns any property to this then the intellisense for this is limited to those assigned properties and ignores the defined type.
🙂 Expected behavior
The issue above seems to only be for function properties with function declarations ie {property: function() {...}} if the function property uses shorthand ie {property() {...}} then the expected behaviour occurs regarding the typing of this, ie there is intellisense based on the defined type of this regardless of what happens in the function (from what I have tried).
For example:

From my understanding the function declaration and shorthand notations shouldnt have different behaviour according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions, so the typing also shouldnt behave differently.
Turning on checkJs fixes the issue however it means migrating to TS is more difficult as all the issues need to be fixed before getting any of the benefits e.g. intellisense, and this also limits functionality for large code bases migrating to TS but with a lot of legacy JS code.
Please provide necessary code as text when it appears in a screenshot
involves JS code which cant be emulated in playground at the moment
The playground supports JS.
involves JS code which cant be emulated in playground at the moment
The playground supports JS.
Cool didnt know that! Still cant use it for this example as it includes both TS and JS files
Please provide necessary code as text when it appears in a screenshot
@RyanCavanaugh See code below from the different files.
tsconfig with allowJs=true on and checkJs=false ie default:
// file: ./tsconfig.json
{
"compilerOptions": {
"noEmit": true,
"allowJs": true,
}
}
File with typed function definition:
// file: ./example1.ts
type SomeAPI = {
apiString: string
apiNumber: number
apiBoolean: boolean
}
type Foo = {
someHandler: (this: SomeAPI) => void
}
function someFunctions(param: Foo) {}
export default someFunctions
JS file with usage of typed function:
// file: ./example2.js
import someFunction from './example1';
someFunction({
someHandler() {
// intellisense shows available `this` API properties
this.
}
})
someFunction({
someHandler() {
this.b = 2;
this.apiBoolean = true;
// intellisense shows available `this` API properties
this.
}
})
someFunction({
someHandler: function() {
// intellisense shows available `this` API properties
this.
}
})
someFunction({
someHandler: function() {
this.apiBoolean = true
// intellisense only shows `apiBoolean` property, expect to show all defined `this` API properties
this.
}
})
Another example with a compact to-the-point code snippet can be found in https://github.com/microsoft/TypeScript/issues/50338
Fixed in nightly version.
https://www.typescriptlang.org/play?ts=4.9.0-dev.20220827&filetype=js#code/LAKA9AVBoAQTABADgQwE4oLYwN44M4D2mApgBIoB2AJgDYloBcMAFAC4AWAlvszrDEGCUSLgGU2aLpQDmzfJOkyBQmCK4A5AK6YARg2aUd+tCqHqAQoUL0qzXdduVQAXwCUMALwA+GADdCLmoXFxhUDGwAWhgAQRgFKVkw9CwAOlgIMFAAMy1KAGM2LkJKeOISADE8wuLKFnCsD34QV1A2kCJSKoKikpZmwU7yKjoGFiazMDAYaTYSWloeEkp8EniOQgB3fDU-FC5aFF16GAADTh5T2IAFAEkwtEIkBiKSfDML-HSQQRdXN3aQ26NT6AzKpAoNHoaHGuA+3C+lkcJCoXhgki0JAA3JNprN5otVis1vgNttdvtDsc1ucEVcYncHk8Xlw3vCeN9fv9AeVgb06mChpDRkwYLkerVYWDBFMZpQ5gslsT1lsdig9gcjidaZcbvckI9nmhXu8fkJPpyYH8QO4eV1qvz+gIhSNocxxSC6hMzYILUibCjSp50WhMbi5QrCctVjASrQAJ4q8mnf1OK4G5nG+MAGhgJAAHs9CujCEm1AsYNQSNlpCRqGdPvTGRmjSb2V8BNb3EA
The fix mentioned above may have addressed this particular issue, but unfortunately it hasn't resolved issues with other similar scenarios.
In related issue https://github.com/microsoft/TypeScript/issues/51359#issuecomment-1312606780, I tested behaviours for various scenarios: with JavaScript and TypeScript, in VS Code and TS Playground, and with short- and long-hand method syntaxes. Those results may be of interest to the TS team. Results varied, but they do seem to confirm that the core problem is the compiler's assumptions for when a function is considered to be a constructor function. Would the solution be to never interpret a (JavaScript) function as a constructor function unless it is preceded by a @constructor JSDoc?
The bug still exists on the latest version
TypeScript v4.9.3 Microsoft Visual Studio Community 2019 v16.11.16