Quick Answer

Variable is not a function or is undefined. Check if function exists, verify object methods, and ensure proper function assignment and scope.

Understanding the Issue

This TypeError indicates an attempt to invoke something that is not callable. Common causes include typos in function names, accessing undefined object methods, overwriting functions with other values, incorrect destructuring, or scope issues where functions are not available. Understanding function types, object method access, and proper function handling prevents these errors.

The Problem

This code demonstrates the issue:

Javascript Error
// Problem 1: Undefined function
function processData() {
    const result = calculateSum(5, 10); // TypeError if calculateSum is not defined
    return result;
}

// Problem 2: Object method not available
const user = {
    name: "John",
    age: 30
};

user.getName(); // TypeError: user.getName is not a function

// Problem 3: Overwritten function
let myFunction = function() {
    return "Hello";
};

myFunction = "not a function anymore";
myFunction(); // TypeError: myFunction is not a function

processData();

The Solution

Here's the corrected code:

Javascript Fixed
// Solution 1: Define functions before use
function calculateSum(a, b) {
    return a + b;
}

function processData() {
    const result = calculateSum(5, 10); // Now works
    console.log("Sum result:", result);
    return result;
}

processData();

// Solution 2: Check if function exists
function safeCall(fn, ...args) {
    if (typeof fn === 'function') {
        return fn(...args);
    } else {
        console.error("Not a function:", typeof fn);
        return null;
    }
}

// Test safe calling
const validFunction = (x) => x * 2;
const notAFunction = "string";

console.log("Safe call result:", safeCall(validFunction, 5));
console.log("Safe call with non-function:", safeCall(notAFunction, 5));

// Solution 3: Proper object methods
const user = {
    name: "John",
    age: 30,
    getName: function() {
        return this.name;
    },
    getInfo() { // Method shorthand
        return `${this.name}, ${this.age}`;
    }
};

// Check if method exists before calling
if (typeof user.getName === 'function') {
    console.log("User name:", user.getName());
}

if (typeof user.getInfo === 'function') {
    console.log("User info:", user.getInfo());
}

// Solution 4: Safe method calling
function callMethod(obj, methodName, ...args) {
    if (obj && typeof obj[methodName] === 'function') {
        return obj[methodName](...args);
    } else {
        console.error(`Method ${methodName} not found or not a function`);
        return undefined;
    }
}

console.log("Safe method call:", callMethod(user, "getName"));
console.log("Safe method call (missing):", callMethod(user, "nonExistent"));

// Solution 5: Safe destructuring with defaults
const utils = {
    add: (a, b) => a + b,
    multiply: (a, b) => a * b
};

// Safe destructuring with fallback functions
const { 
    add, 
    subtract = (a, b) => {
        console.warn("Subtract function not available, using default");
        return a - b;
    }
} = utils;

console.log("Add result:", add(10, 5));
console.log("Subtract result:", subtract(10, 5)); // Uses default

Key Takeaways

Always check if a variable is a function using typeof before calling. Define functions before use. Protect important functions from being overwritten. Use safe destructuring with default functions.