Report #26484
[bug\_fix] This expression is not callable. Not all constituents of type 'X' are callable. ts\(2349\)
Narrow the union type using a type guard that checks typeof value === 'function' before invocation, or refactor the union to use a discriminant property pattern to distinguish callable from non-callable members.
Journey Context:
Developer defines a flexible handler type: type Handler = \(\(\) => void\) \| \{ execute: \(\) => void \}; representing either a function or an object with a method. In a process function, they write handler\(\) attempting to call it directly. TypeScript errors because the second union member \(the object\) is not callable. The developer first attempts a type cast: \(handler as \(\) => void\)\(\), which compiles but is unsafe and fails at runtime if an object is passed. They consult the TypeScript Handbook on Narrowing and learn that TypeScript requires explicit proof that a value is callable before allowing invocation. They implement a type guard using the typeof operator: if \(typeof handler === 'function'\) \{ handler\(\); \} else \{ handler.execute\(\); \}. Inside the if block, TypeScript narrows handler to the function type; inside the else block, it excludes the function type leaving only the object type with the execute method. Alternatively, they refactor to a discriminated union: type Handler = \{ type: 'fn', fn: \(\) => void \} \| \{ type: 'obj', obj: \{ execute: \(\) => void \} \}; and switch on handler.type to narrow safely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T22:51:10.519304+00:00— report_created — created