error TS2722: Cannot invoke an object which is possibly 'undefined'. is reported when code calls something whose type is a function or undefined: an optional callback in an options object, an optional method, a function looked up in a map.
In JavaScript APIs this is the onProgress or onError option that callers usually leave out. The type says it is optional, so calling it without a check would throw TypeError: options.onProgress is not a function for every caller who left it out.
At a glance
| Code | TS2722 |
|---|---|
| Message | Cannot invoke an object which is possibly 'undefined'. |
| TypeScript's category | error |
| Listed under | Null, undefined and unknown |
| Turned on by | strictNullChecks, strict |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0).
What it looks like
/**
* @param {File} file
* @param {{ onProgress?: (percent: number) => void }} [options]
*/
export function upload(file, options = {}) {
options.onProgress(0);error TS2722: Cannot invoke an object which is possibly 'undefined'.
return file.name;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- A property declared with
?(or a parameter marked optional) holds a function, and the code calls it directly. strictNullChecks(part ofstrict) is on.
How to fix it
Call it with ?.()
options.onProgress?.(0) calls the function when it is there and does nothing otherwise. Destructuring with a default, { onProgress = () => {} } = {}, does the same once for the whole function.
/**
* @param {File} file
* @param {{ onProgress?: (percent: number) => void }} [options]
*/
export function upload(file, options = {}) {
options.onProgress?.(0);
return file.name;
}
/**
* @param {File} file
* @param {{ onProgress?: (percent: number) => void }} [options]
*/
export function uploadQuietly(file, { onProgress = () => {} } = {}) {
onProgress(0);
return file.name;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Gotchas
- Destructuring without a default (
const { onProgress } = options) does not change anything: callingonProgress(0)is TS2722 too. - If the function is required in practice, remove the
?from its property; callers that leave it out are then reported where they are written.
Sources
- Optional chaining (?.) · MDN Web Docs
- TSConfig Reference: strictNullChecks · TypeScript
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.