How to fix Cannot invoke an object which is possibly 'undefined'. in TypeScript
TypeScript in strict mode prevents calling functions or methods that could be undefined. This error occurs when optional function properties or return values lack proper null/undefined checks before invocation.
Quick fix
Fixes Cannot invoke an object which is possibly 'undefined'.
// Before: Error - possibly undefined
const callback: ((value: number) => void) | undefined = getCallback();
callback(42); // TS2722 error
// After: Using optional chaining with optional call
callback?.(42); // Safe - returns undefined if callback is undefined
// Optional call on object property
const config: { onSave?: (data: any) => void } = getConfig();
config.onSave?.({ /* data */ }); // Safe invocation- Use optional chaining with optional call (?.()
- Add explicit null/undefined checks with if statement
- Use typeof operator for more precise checks
- Provide a default function or handler
// Before: Error - possibly undefinedconst callback: ((value: number) => void) | undefined = getCallback();callback(42); // TS2722 error// After: Using optional chaining with optional callcallback?.(42); // Safe - returns undefined if callback is undefined// Optional call on object propertyconst config: { onSave?: (data: any) => void } = getConfig();config.onSave?.({ /* data */ }); // Safe invocationCannot invoke an object which is possibly 'undefined'.
What this error means
This TypeScript error (TS2722) occurs when you attempt to call a function or method that TypeScript cannot guarantee exists. In strict mode, TypeScript treats null and undefined as distinct types and requires explicit handling. When you have a variable or property whose type includes undefined (like optional parameters, optional properties, or functions that might return undefined), TypeScript prevents you from directly invoking or calling it without first checking that it's not undefined. This error is a type safety mechanism designed to prevent the common JavaScript runtime error "Cannot read property of undefined" by catching the problem at compile time instead.
Typical symptoms
- TypeScript compiler error: "error TS2722: Cannot invoke an object which is possibly 'undefined'"
- Error appears on function call expressions like someFunc()
- Error appears when calling optional properties like obj.method?.()
- Error references a specific line and column in your TypeScript file
- Linter or IDE shows the error with a red underline
- Build process fails with TS2722 in strict mode
- The variable or function property has type that includes undefined
Common causes
- Calling a function property on an object without checking if the property exists
- Invoking the result of a function that might return undefined
- Calling an optional function parameter without type narrowing
- Using a function returned from another function that could be undefined
- Accessing methods on nullable types without null checks
- Parameter or variable typed with 'T | undefined' without narrowing
- Missing strict null check guards before function invocation
How to fix "Cannot invoke an object which is possibly 'undefined'."
The optional chaining operator (?.) combined with optional call (?.) safely handles undefined values. If the function is undefined, the expression returns undefined instead of throwing an error.
// Before: Error - possibly undefined
const callback: ((value: number) => void) | undefined = getCallback();
callback(42); // TS2722 error
// After: Using optional chaining with optional call
callback?.(42); // Safe - returns undefined if callback is undefined
// Optional call on object property
const config: { onSave?: (data: any) => void } = getConfig();
config.onSave?.({ /* data */ }); // Safe invocationOptional chaining short-circuits when it encounters undefined or null, preventing the call from executing and returning undefined instead.
Before calling the function, explicitly check that it is not undefined or null. This is a classic type narrowing approach.
// Before: Error - possibly undefined
const handler: ((event: Event) => void) | undefined = getEventHandler();
handler(event); // TS2722 error
// After: Explicit null check
if (handler !== undefined) {
handler(event); // Type narrowed to (event: Event) => void
}
// Alternative: Check both null and undefined
if (handler != null) {
handler(event);
}
// Using logical AND operator
handler && handler(event); // Only calls if handler is truthyThe type narrowing ensures TypeScript understands that inside the if block, handler cannot be undefined.
The typeof operator helps verify that a value is actually a function before attempting to call it.
// Before: Error - possibly undefined
const maybeFn: Function | undefined = getValue();
maybeFn(); // TS2722 error
// After: Using typeof check
if (typeof maybeFn === 'function') {
maybeFn(); // Now TypeScript knows it's a function
}
// With more complex types
const obj: { compute?: (x: number) => number } = getObject();
if (typeof obj.compute === 'function') {
const result = obj.compute(10); // Safe to call
}The typeof check narrows the type from "possibly undefined" to definitely a function.
If a function is optional but you need a fallback, use the nullish coalescing operator (??) or logical OR (||) to provide a default.
// Before: Error - possibly undefined
const callback: ((data: any) => void) | undefined = config.onSuccess;
callback(data); // TS2722 error
// After: Provide default function
const handler = callback ?? (() => {}); // Use empty function if callback is undefined
handler(data); // Safe - always a function
// Alternative with logical OR
const onSuccess = config.onSuccess || ((result) => console.log(result));
onSuccess(data);
// Inline arrow function as default
const processCallback = (cb: ((x: number) => string) | undefined) => {
const actual = cb ?? (x => x.toString());
return actual(42); // Always valid
};This approach ensures the variable is never undefined before calling it.
Instead of marking a parameter as optional (possibly undefined), provide a default function value.
// Before: Error - onComplete might be undefined
function fetchData(url: string, onComplete?: (result: any) => void) {
fetch(url)
.then(r => r.json())
.then(data => onComplete(data)); // TS2722 error
}
// After: Provide default function
function fetchData(url: string, onComplete: (result: any) => void = () => {}) {
fetch(url)
.then(r => r.json())
.then(data => onComplete(data)); // Safe - onComplete is always a function
}
// Alternative: Create wrapper to handle undefined
function fetchData(url: string, onComplete?: (result: any) => void) {
fetch(url)
.then(r => r.json())
.then(data => {
if (onComplete) {
onComplete(data); // Type narrowed in this scope
}
});
}Default values eliminate the undefined state, simplifying your code.
If you know a function is always present, remove undefined from the type annotation. If it might not exist, handle it with the techniques above.
// Before: Type includes undefined
interface EventConfig {
onEvent?: (event: Event) => void; // May be undefined
}
function triggerEvent(config: EventConfig, event: Event) {
config.onEvent(event); // TS2722 error
}
// After: Mark as required or use proper guards
interface EventConfig {
onEvent: (event: Event) => void; // Required - never undefined
}
function triggerEvent(config: EventConfig, event: Event) {
config.onEvent(event); // Safe - always defined
}
// Or keep optional but handle it
function triggerEvent(config: EventConfig, event: Event) {
config.onEvent?.(event); // Optional chaining handles undefined
}Clearing up type annotations makes the intent of your code explicit.
Ensure strict null checking is enabled in your TypeScript configuration to catch these issues early.
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"target": "ES2020",
"module": "ESNext"
}
}Or use the "strict" option which enables strictNullChecks and other safety checks:
{
"compilerOptions": {
"strict": true
}
}Strict mode catches these errors at compile time rather than runtime.
Verify that your changes resolve the TS2722 error by running the TypeScript compiler.
# Check for TypeScript errors
npx tsc --noEmit
# Or using npm/yarn scripts
npm run type-check
yarn type-check
# Watch mode during development
npx tsc --watchThe error should no longer appear once your code properly handles possibly undefined values.
Advanced notes
Optional Chaining vs. Logical AND: Optional chaining (?.) is the preferred modern approach (ES2020+) because it's more explicit and handles all falsy values gracefully. Logical AND (&&) also works but checks for all falsy values, not just null/undefined. Use optional chaining when targeting modern environments.
Type Narrowing with Function Types: TypeScript's type narrowing only works within the scope where the check occurs. If you check inside an if block, the narrowed type only applies within that block. Outside, the original type (with undefined) applies again.
Function Overloading: For complex functions with optional callbacks, consider using function overloads to explicitly specify which parameter combinations are valid:
function process(data: string, callback: (result: string) => void): void;
function process(data: string): string;
function process(data: string, callback?: (result: string) => void) {
const result = transform(data);
callback?.(result);
return result;
}Assertion Functions: TypeScript 3.7+ supports assertion functions to verify conditions:
function assertIsFunction(value: unknown): asserts value is Function {
if (typeof value !== 'function') {
throw new Error('Value must be a function');
}
}
const callback: (() => void) | undefined = getCallback();
assertIsFunction(callback);
callback(); // Safe - TypeScript knows it's a functionStrict Mode Trade-offs: While strict mode prevents bugs, it requires more explicit type handling. The initial verbosity pays off in long-term maintainability and fewer runtime errors.
Frequently asked questions
- What does "Cannot invoke an object which is possibly 'undefined'." mean?
- This TypeScript error (TS2722) occurs when you attempt to call a function or method that TypeScript cannot guarantee exists. In strict mode, TypeScript treats null and undefined as distinct types and requires explicit handling. When you have a variable or property whose type includes undefined (like optional parameters, optional properties, or functions that might return undefined), TypeScript prevents you from directly invoking or calling it without first checking that it's not undefined.
- How do I fix "Cannot invoke an object which is possibly 'undefined'."?
- TypeScript in strict mode prevents calling functions or methods that could be undefined. This error occurs when optional function properties or return values lack proper null/undefined checks before invocation.
- What causes "Cannot invoke an object which is possibly 'undefined'."?
- Calling a function property on an object without checking if the property exists Invoking the result of a function that might return undefined Calling an optional function parameter without type narrowing
- Is the "Cannot invoke an object which is possibly 'undefined'." error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖Official: Type Narrowing in TypeScript(Official Docs)
- 📖Official: TypeScript 3.7 - Optional Chaining(Official Docs)
- 💬GitHub Issue: TSC Strict mode error TS2722(Stack Overflow)
- 📖Official: Truthiness Narrowing(Official Docs)