How to fix This expression is not callable in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 135 views

This TypeScript error occurs when you attempt to invoke a value that doesn't have a call signature—essentially trying to call something that isn't a function. Common causes include calling non-function types, incorrect imports, type mismatches, and union types that confuse the compiler.

Quick fix

Fixes TS2349

// WRONG: Calling a string
const message = "Hello, world!";
message(); // Error: This expression is not callable. Type 'String' has no call signatures.

// WRONG: Calling a number
const count = 100;
count(); // Error: This expression is not callable. Type 'Number' has no call signatures.

// CORRECT: Call an actual function
const greet = () => "Hello, world!";
greet(); // Works fine
  1. Verify the value is actually a function
  2. Fix incorrect imports
  3. Remove or fix type assertions
  4. Narrow union types before calling
typescript — error
// WRONG: Calling a string
const message = "Hello, world!";
message(); // Error: This expression is not callable. Type 'String' has no call signatures.
// WRONG: Calling a number
const count = 100;
count(); // Error: This expression is not callable. Type 'Number' has no call signatures.
// CORRECT: Call an actual function
const greet = () => "Hello, world!";
greet(); // Works fine
This expression is not callable

What this error means

TypeScript's type system ensures type safety by tracking which values are callable (functions) and which are not. When you try to invoke an expression using parentheses `()`, TypeScript verifies that the expression has a call signature. If it doesn't, the compiler emits error TS2349: "This expression is not callable." This error typically appears in several scenarios: 1. **Calling a non-function type**: You're trying to call a string, number, object, or other non-function value as if it were a function 2. **Type assertion issues**: The value is actually a function, but TypeScript has been told (via type assertions or incorrect typing) that it's something else 3. **Import/module problems**: You've imported an object instead of a function, or the default export isn't what you expected 4. **Union type confusion**: When working with union types that include functions, TypeScript can't safely determine which type you have Unlike JavaScript, which throws runtime errors when you call non-functions, TypeScript catches these mistakes at compile time, preventing potentially confusing bugs from reaching production.

Typical symptoms

  • Compiler error TS2349 with message 'This expression is not callable'
  • Error message includes 'Type X has no call signatures'
  • Red squiggly line in IDE under function call syntax (parentheses)
  • Build fails despite the code looking syntactically correct
  • Error appears when calling array methods like .map() on union types
  • Import statements work but calling the imported value fails
  • Using module: 'NodeNext' causes callable errors on valid functions

Common causes

  1. Attempting to call a string, number, boolean, or other primitive as a function
  2. Calling an object or array without accessing a method property first
  3. Type assertion incorrectly declares a function as a non-callable type
  4. Importing a namespace or module object instead of a specific exported function
  5. Union type includes function and non-function types without type narrowing
  6. Default export differs from named exports in ESM/CJS interoperability
  7. Property access returns 'never' type due to conflicting type guards
  8. Generic type constraints don't include call signatures
  9. Conditional types evaluate to non-callable types in certain branches

How to fix "This expression is not callable"

1Verify the value is actually a function

First, check what type TypeScript thinks the value is. Hover over the identifier in your IDE to see the inferred type:

typescript
// WRONG: Calling a string
const message = "Hello, world!";
message(); // Error: This expression is not callable. Type 'String' has no call signatures.

// WRONG: Calling a number
const count = 100;
count(); // Error: This expression is not callable. Type 'Number' has no call signatures.

// CORRECT: Call an actual function
const greet = () => "Hello, world!";
greet(); // Works fine

Use console.log(typeof value) at runtime or check the type annotation in your editor to confirm the value is indeed a function.

2Fix incorrect imports

This error commonly occurs when you import an object/namespace instead of a function. Ensure you're accessing the correct export:

typescript
// utils.ts
export const helpers = {
  formatDate: (date: Date) => date.toLocaleDateString(),
  formatNumber: (num: number) => num.toFixed(2),
};

// WRONG: Importing the whole object
import { helpers } from "./utils";
helpers(); // Error: This expression is not callable

// CORRECT: Access the method property
import { helpers } from "./utils";
helpers.formatDate(new Date()); // Works

// OR: Import a specific function if exported separately
export const formatDate = (date: Date) => date.toLocaleDateString();
import { formatDate } from "./utils";
formatDate(new Date()); // Works

For default exports with module interop issues:

typescript
// Common with libraries like mitt, lodash in NodeNext mode
// WRONG
import mitt from "mitt"; // mitt might be namespace, not function
mitt(); // Error

// CORRECT
import mitt from "mitt";
const emitter = mitt(); // If mitt is the factory, this works
// OR check library docs for correct import syntax
3Remove or fix type assertions

Type assertions can override TypeScript's inference, causing it to treat functions as non-callable types:

typescript
// WRONG: Asserting a function as a string
const myFunc = (() => "test") as unknown as string;
myFunc(); // Error: This expression is not callable

// CORRECT: Don't use incorrect assertions
const myFunc = () => "test";
myFunc(); // Works

// Example with objects
interface Config {
  handler: () => void;
}

const config = {
  handler: () => console.log("running"),
} as Config;

config.handler(); // Works because type is correct

If you must use type assertions, ensure the target type includes call signatures:

typescript
type CallableType = (...args: any[]) => any;
const func = someValue as unknown as CallableType;
func(); // Now TypeScript knows it's callable
4Narrow union types before calling

When a variable can be multiple types (union type), TypeScript won't let you call it unless you prove it's a function:

typescript
type Handler = string | (() => string);

// WRONG: Calling without type check
function process(handler: Handler) {
  return handler(); // Error: This expression is not callable
}

// CORRECT: Type guard before calling
function process(handler: Handler) {
  if (typeof handler === "function") {
    return handler(); // TypeScript knows it's a function here
  }
  return handler; // String case
}

// React example with union types
type FailedContent = string | JSX.Element | (() => JSX.Element);

function renderFailed(content: FailedContent) {
  // WRONG
  // return content(); // Error

  // CORRECT
  if (typeof content === "function") {
    return content();
  }
  return content;
}

Common type guard patterns:

typescript
// For functions
if (typeof value === "function") { /* ... */ }

// For objects with callable properties
if (value && typeof value.method === "function") { /* ... */ }

// Custom type predicate
function isFunction(value: unknown): value is Function {
  return typeof value === "function";
}
5Fix array method calls on union types

TypeScript may report this error when calling .map(), .filter(), or .reduce() on arrays with complex union types:

typescript
// Problem scenario
type Data = string[] | { items: string[] };

function process(data: Data) {
  // Error: This expression is not callable
  return data.map((item) => item.toUpperCase());
}

// SOLUTION 1: Type guard
function process(data: Data) {
  if (Array.isArray(data)) {
    return data.map((item) => item.toUpperCase());
  }
  return data.items.map((item) => item.toUpperCase());
}

// SOLUTION 2: Normalize to array first
function process(data: Data) {
  const arr = Array.isArray(data) ? data : data.items;
  return arr.map((item) => item.toUpperCase());
}

If using libraries with complex types, ensure your TypeScript version is up to date—older versions had bugs with union type inference for built-in methods.

6Check tsconfig module settings for ESM/CJS issues

The module and moduleResolution settings can affect how imports are typed, especially with "module": "NodeNext":

json
// tsconfig.json
{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}

If you're getting "Type 'typeof import(...)' has no call signatures" errors:

1. Check library typings: Some libraries (like mitt, older versions of packages) may not have proper ESM type definitions
2. Use esModuleInterop: Add "esModuleInterop": true to tsconfig.json
3. Access the correct export:

typescript
// If library exports object
import * as MyLib from "my-lib";
MyLib.default(); // Call the default export

// OR
import MyLib from "my-lib";
MyLib(); // If default is the function

4. Update library: Check if a newer version has better TypeScript support

Advanced notes

### Function Overloads and Call Signatures

TypeScript uses call signatures to determine if a type is callable. You can explicitly define call signatures in interfaces and types:

typescript
// Interface with call signature
interface Callable {
  (): string; // Call signature
  property: number;
}

const myFunc: Callable = Object.assign(
  () => "result",
  { property: 42 }
);

myFunc(); // Works - has call signature
myFunc.property; // Also works

### Generic Constraints for Callable Types

When working with generics, you can constrain type parameters to be callable:

typescript
// WRONG: Generic without constraint
function invoke<T>(fn: T) {
  return fn(); // Error: This expression is not callable
}

// CORRECT: Constrain T to be callable
function invoke<T extends (...args: any[]) => any>(fn: T) {
  return fn(); // Works
}

// Or use Function type (less type-safe)
function invoke(fn: Function) {
  return fn(); // Works but loses parameter/return type info
}

### Conditional Types and Callable Resolution

Complex conditional types can result in non-callable types in certain branches:

typescript
type Result<T> = T extends string ? () => T : T;

function process<T>(value: Result<T>) {
  // Error: Can't call - might be T or (() => T)
  return value();
}

// Solution: Type narrowing
function process<T>(value: Result<T>) {
  if (typeof value === "function") {
    return value();
  }
  return value;
}

### React Component Callable Issues

In React with TypeScript, you might encounter this with render props or function components:

typescript
type RenderProp = string | (() => JSX.Element);

// WRONG
function MyComponent({ render }: { render: RenderProp }) {
  return <div>{render()}</div>; // Error if render is string
}

// CORRECT
function MyComponent({ render }: { render: RenderProp }) {
  const content = typeof render === "function" ? render() : render;
  return <div>{content}</div>;
}

### Debugging with Type Utilities

Use TypeScript utility types to inspect what TypeScript thinks is callable:

typescript
// Check if type has call signature
type IsCallable<T> = T extends (...args: any[]) => any ? true : false;

type Test1 = IsCallable<() => void>; // true
type Test2 = IsCallable<string>; // false
type Test3 = IsCallable<typeof Math.random>; // true

### Module Augmentation and Declaration Merging

If you're extending third-party types, ensure you don't accidentally remove call signatures:

typescript
// WRONG: Replaces instead of merging
declare module "my-lib" {
  const myFunc: { property: string }; // Lost call signature
}

// CORRECT: Merge with existing
declare module "my-lib" {
  interface MyFunc {
    property: string; // Adds property, preserves call signature
  }
}

Frequently asked questions

What does "TS2349" mean?
TypeScript's type system ensures type safety by tracking which values are callable (functions) and which are not. When you try to invoke an expression using parentheses (), TypeScript verifies that the expression has a call signature. " This error typically appears in several scenarios: 1.
How do I fix "TS2349"?
This TypeScript error occurs when you attempt to invoke a value that doesn't have a call signature—essentially trying to call something that isn't a function. Common causes include calling non-function types, incorrect imports, type mismatches, and union types that confuse the compiler.
What causes "TS2349"?
Attempting to call a string, number, boolean, or other primitive as a function Calling an object or array without accessing a method property first Type assertion incorrectly declares a function as a non-callable type
Is the "TS2349" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading