TS2349Semantic Error
Since TS 1.0Updated in TS 2.1Updated in TS 3.6

Fix TS2349: This Expression Is Not Callable

Learn why TypeScript throws TS2349 when you call a value that has no call signature, and how to fix non-functions, wrong call sites, and unions.

error TS2349: This expression is not callable

What This Error Means

TypeScript error TS2349 means you put ( after something that cannot be called. The compiler resolved the type of the expression in front of the parentheses, looked for a call signature on it, and found none.

The interesting part is always the second line. Since TypeScript 3.6 the compiler prints an elaboration under the headline that names the exact reason, and there are three different ones:

const orderCount = 3
orderCount()
~~~~~~~~~~
Error: This expression is not callable.
         Type 'Number' has no call signatures.                       // plain non-function
         Not all constituents of type 'X | Y' are callable.          // union with a non-callable member
         Each member of the union type 'A | B' has signatures, but
         none of those signatures are compatible with each other.    // union of incompatible functions

If you are reading an older Stack Overflow answer you will see a different wording for the same code: TypeScript 1.x through 3.5 reported "Cannot invoke an expression whose type lacks a call signature. Type 'X' has no compatible call signatures." The check is unchanged; only the message was rewritten (in 2.1, then again in 3.6). No compiler flag turns TS2349 on or off — it is part of the core checker and fires even without strict.

Common Causes

1. The Value Is Not a Function

The classic version of this is a React hook: useState hands back a tuple of [value, setter], and it is easy to call the value. The same slip happens with any destructured tuple.

// ❌ Broken
function useCounter(initial: number): [number, (next: number) => void] {
  let value = initial
  return [value, (next: number) => { value = next }]
}
 
const [count, setCount] = useCounter(0)
 
count(count + 1)
// ~~~~~ Error: This expression is not callable.
//         Type 'Number' has no call signatures. (TS2349)
// ✅ Fixed — call the setter, not the current value
function useCounter(initial: number): [number, (next: number) => void] {
  let value = initial
  return [value, (next: number) => { value = next }]
}
 
const [count, setCount] = useCounter(0)
 
setCount(count + 1)

The elaboration is worth reading literally here: Type 'Number' has no call signatures (capital N) tells you the callee is a primitive number, which usually points straight at the destructuring order.

2. Calling the Object That Holds the Function

API clients, config objects and namespace imports all wrap the function you actually want. Calling the wrapper gives you TS2349 with the full object type printed in the elaboration.

// ❌ Broken
const ordersApi = {
  fetchOrders(customerId: string) {
    return fetch(`/api/customers/${customerId}/orders`)
  },
}
 
const orders = ordersApi("cus_1024")
//             ~~~~~~~~~ Error: This expression is not callable.
//               Type '{ fetchOrders(customerId: string): Promise<Response>; }'
//               has no call signatures. (TS2349)
// ✅ Fixed — call the method on the object
const ordersApi = {
  fetchOrders(customerId: string) {
    return fetch(`/api/customers/${customerId}/orders`)
  },
}
 
const orders = ordersApi.fetchOrders("cus_1024")

The import version of this is import * as formatDate from "date-helper" followed by formatDate(...). A namespace object is never callable, no matter what the module exports at runtime — switch to the default or named import, and turn on esModuleInterop if the package only has a CommonJS module.exports = fn.

3. A Union That Mixes a Function With a Value

Config shapes love this pattern: a price that is either a fixed number or a function of quantity, a label that is either a string or a getter. The union is only callable if every member is.

// ❌ Broken
type Price = number | ((quantity: number) => number)
 
declare const unitPrice: Price
 
const total = unitPrice(3)
//            ~~~~~~~~~ Error: This expression is not callable.
//              Not all constituents of type 'Price' are callable.
//                Type 'number' has no call signatures. (TS2349)
// ✅ Fixed — narrow with a typeof guard, then call
type Price = number | ((quantity: number) => number)
 
declare const unitPrice: Price
 
const total = typeof unitPrice === "function" ? unitPrice(3) : unitPrice * 3

typeof x === "function" is a real type guard in TypeScript, so inside the true branch unitPrice is narrowed to the function member and the call type-checks. The else branch is not busywork either — it is the value case you designed into the type in the first place.

4. A Union of Two Function Types That Cannot Be Combined

When every member of the union is callable, TypeScript tries to synthesize one signature that covers all of them. Generic signatures and overloads often make that impossible — and then you get the third elaboration.

// ❌ Broken
interface Order { id: string; createdAt: Date; status: string }
 
type SortRows = <T extends { createdAt: Date }>(rows: T[]) => T[]
type GroupRows = <T extends { status: string }>(rows: T[]) => Record<string, T[]>
 
declare const orders: Order[]
declare const transform: SortRows | GroupRows
 
const result = transform(orders)
//             ~~~~~~~~~ Error: This expression is not callable.
//               Each member of the union type 'SortRows | GroupRows' has
//               signatures, but none of those signatures are compatible
//               with each other. (TS2349)
// ✅ Fixed — one signature, union in the return type
interface Order { id: string; createdAt: Date; status: string }
 
type TransformRows = (rows: Order[]) => Order[] | Record<string, Order[]>
 
declare const orders: Order[]
declare const transform: TransformRows
 
const result = transform(orders)

Watch the neighbours here. If the union members differ only in how many parameters they take, TypeScript picks the longest signature and reports TS2554 ("Expected 2 arguments, but got 1") instead. If they differ only in parameter type, the parameters intersect to never and you get TS2345. TS2349 is specifically the case where no combined signature exists at all.

How to Fix It

  1. Read the second line of the error, then hover the callee. "This expression is not callable" is the same sentence for every cause; the elaboration underneath names the offending type. Type 'X' has no call signatures means the value is not a function at all, Not all constituents means one union member is not callable, and none of those signatures are compatible means all of them are functions but cannot be merged. In most real cases the type it prints points straight at the fix, and that fix is at the call site: you meant setCount, not count; ordersApi.fetchOrders, not ordersApi; dateFns.format, not the namespace object.

  2. Narrow value-or-function unions with typeof. typeof candidate === "function" is a real type guard, so the callable member survives inside the true branch. It works on properties too, which is where these unions usually hide:

type Handlers = { onSave: () => void } | { onSave: string }
 
declare const handlers: Handlers
 
if (typeof handlers.onSave === "function") {
  handlers.onSave()
}
  1. Collapse unions of functions into a single signature. A union of function types is not a set of overloads — TypeScript will not pick one for you, and no runtime check can narrow between two functions. Declare one signature whose parameters are unions ((id: string | number, force?: boolean) => void), or discriminate on a sibling field before calling. The same applies to arrays: prefer (Order | Draft)[] over Order[] | Draft[], because a method call on an array union is a call on a union of method signatures.

  2. Constrain generics you intend to call. A bare type parameter has no call signature, so calling it fails even when every caller passes a function. Add the constraint instead of casting:

// ❌ Error: This expression is not callable.
//            Type 'unknown' has no call signatures. (TS2349)
function runTask<T>(task: T) {
  return task()
}
// ✅ The constraint gives T a call signature
function runTask<T extends (...args: never[]) => unknown>(task: T) {
  return task()
}
  1. Do not reach for as any or as Function. Casting silences TS2349 and moves the failure to runtime as TypeError: x is not a function — which is exactly the bug the compiler just caught. If you genuinely know better than the type, narrow to the precise signature with a type guard rather than erasing it. Then keep the error from coming back: type the source of the value — the API client, the config object, the prop — with one concrete call signature instead of a union, so the next reader cannot call the wrong thing.

FAQ

What causes TypeScript error TS2349?

TS2349 fires when the expression in front of ( has a type with zero call signatures. There are three shapes: the value is not a function (a number, a string, an object, a namespace import), the value is a union in which at least one member is not callable, or the value is a union of function types whose signatures cannot be combined into one. The elaboration line under the headline tells you which of the three you hit. No compiler flag controls the check — it fires in non-strict projects too.

How do I fix "This expression is not callable" on a union type?

It depends on which union you have. If the union mixes a value and a function — number | ((q: number) => number) — guard with typeof unitPrice === "function" and handle both branches. If every member is a function, narrowing will not help, because there is nothing to discriminate on: replace the union of signatures with one signature that takes union parameters, or restructure the type so a discriminant property tells you which function you are holding before you call it.

Why does .filter() give TS2349 on an array union when .map() does not?

Because rows.filter(...) on a value of type string[] | number[] is a call on a union of two filter signatures, and until TypeScript 5.2 the compiler could not produce a combined signature for the callback-taking methods filter, find, every and reduce; map reduced cleanly and so appeared to work. TypeScript 5.2 fixed this class of calls, so on a current compiler the snippet below is clean:

declare const rows: string[] | number[]
 
// TS2349 on TypeScript 5.1 and earlier, fine from 5.2 on
const filled = rows.filter((row) => Boolean(row))

If you cannot upgrade, declare the value as (string | number)[] — a single array type with a union element type — and every method call works on any version.

Related Errors

Practice This

Browse all TypeScript practice challenges to keep sharpening your type-level skills.

Related Concepts

Share this reference

Become a TypeScript Pro

Track your progress through 100+ hands-on challenges. Free, sign in with GitHub.

Or start solving right away: explore all TypeScript challenges