This TypeScript error occurs when you call a function with arguments that don't match any of its defined overload signatures. The fix involves checking the function's overload signatures, ensuring argument types match, or using type assertions when TypeScript can't infer the correct overload.
The "No overload matches this call" error (TS2769) appears when TypeScript cannot find a matching function overload for the arguments you're passing. TypeScript overloads allow a single function to have multiple call signatures with different parameter types and return types. When you call an overloaded function, TypeScript tries to match your arguments against each overload signature in order. If none match, you get this error. This typically happens when: 1. **Argument type mismatches**: You're passing arguments of the wrong type 2. **Missing optional parameters**: You're omitting required parameters or providing too many arguments 3. **Union type issues**: Your arguments have union types that don't match any single overload 4. **Generic constraints**: Generic type parameters can't be inferred from the arguments Overloads are common in library functions (like document.createElement, fetch, Array methods) and in your own code when functions need to handle multiple input patterns.
First, examine the function's type definition to understand what overloads are available:
// Example: document.createElement has multiple overloads
declare function createElement(tagName: "div"): HTMLDivElement;
declare function createElement(tagName: "span"): HTMLSpanElement;
declare function createElement(tagName: string): HTMLElement;
// This works - matches first overload
const div = document.createElement("div");
// This fails - "button" doesn't match specific overloads
const button = document.createElement("button"); // Error: No overload matches this callHover over the function in your IDE to see available overloads. In VS Code, press Ctrl/Cmd and click the function name to jump to its definition.
Ensure your arguments match the expected types in the overload signatures:
// Example: Array.from has overloads for different input types
// Overload 1: Array.from<T>(arrayLike: ArrayLike<T>): T[];
// Overload 2: Array.from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
// WRONG - second argument should be a function
const result1 = Array.from([1, 2, 3], "string"); // Error
// CORRECT - second argument is a mapping function
const result2 = Array.from([1, 2, 3], x => x * 2); // Works
// WRONG - object doesn't match expected interface
function process(options: { name: string }): void;
function process(options: { id: number }): void;
process({ title: "test" }); // Error - no overload matches
// CORRECT - matches one of the overloads
process({ name: "John" }); // Works
process({ id: 123 }); // WorksWhen arguments have union types, TypeScript needs each argument to match a single overload:
// Function with overloads
function format(input: string): string;
function format(input: number): number;
// WRONG - union type doesn't match any single overload
function processValue(value: string | number) {
return format(value); // Error: No overload matches this call
}
// SOLUTION 1: Type narrowing
function processValue(value: string | number) {
if (typeof value === "string") {
return format(value); // Works - matches string overload
} else {
return format(value); // Works - matches number overload
}
}
// SOLUTION 2: Add a union overload
function format(input: string): string;
function format(input: number): number;
function format(input: string | number): string | number; // Add union overload
function format(input: any): any {
// Implementation
}
// SOLUTION 3: Use function overload with generic
function format<T extends string | number>(input: T): T;
function format(input: any): any {
return input;
}When TypeScript can't infer the correct overload, use type assertions:
// Example with fetch API
// fetch has overloads for RequestInfo (string | Request) and optional RequestInit
// WRONG - TypeScript can't infer which overload
const url: string | URL = Math.random() > 0.5 ? "https://api.com" : new URL("https://api.com");
fetch(url); // Error: No overload matches this call
// SOLUTION 1: Type assertion
fetch(url as string); // Assert it's a string
// or
fetch(url as Request); // Assert it's a Request
// SOLUTION 2: Narrow the type
if (typeof url === "string") {
fetch(url); // Works - matches string overload
} else {
fetch(url); // Works - matches Request overload
}
// Example with generic constraints
function process<T extends string | number>(value: T): T {
// Some processing
return value;
}
// WRONG - TypeScript can't match overload
const result = process(Math.random() > 0.5 ? "text" : 123); // Error
// SOLUTION - Add explicit type parameter
const result = process<string | number>(Math.random() > 0.5 ? "text" : 123);Sometimes the error comes from mismatched type definitions:
# Check TypeScript version
npx tsc --version
# Check if library types are installed
npm list @types/library-name
# Update TypeScript
npm install typescript@latest --save-dev
# Update type definitions
npm install @types/library-name@latest --save-dev
# If using a specific version, ensure compatibility
# Check the library's documentation for TypeScript version requirementsCommon issues:
- Library updated but @types package hasn't been updated
- TypeScript version too old for new library features
- Conflicting type definitions from multiple @types packages
Check the library's GitHub issues for similar problems:
https://github.com/DefinitelyTyped/DefinitelyTyped/issues?q=no+overload+matches
https://github.com/microsoft/TypeScript/issues?q=TS2769If you're writing overloaded functions, structure them for better type inference:
// POOR DESIGN - hard to match
function process(data: string, count: number): string;
function process(data: number, prefix: string): number;
function process(data: any, second: any): any {
// Implementation
}
// BETTER DESIGN - use discriminated unions
type StringInput = { type: "string"; data: string; count: number };
type NumberInput = { type: "number"; data: number; prefix: string };
type ProcessInput = StringInput | NumberInput;
function process(input: ProcessInput): string | number {
if (input.type === "string") {
return `${input.data} repeated ${input.count} times`;
} else {
return `${input.prefix}${input.data}`;
}
}
// EVEN BETTER - use function overloads with clearer signatures
function process(data: string, count: number): string;
function process(data: number, prefix: string): number;
function process(data: string | number, second: string | number): string | number {
if (typeof data === "string") {
// TypeScript knows second is number here
return data.repeat(second as number);
} else {
// TypeScript knows second is string here
return `${second}${data}`;
}
}
// Add a catch-all signature if needed
function process(data: string, count: number): string;
function process(data: number, prefix: string): number;
function process(data: any, second: any): any; // Catch-all
function process(data: any, second: any): any {
// Implementation
}### How TypeScript Resolves Overloads
TypeScript uses a process called overload resolution to determine which overload matches a function call:
1. Exact match checking: TypeScript looks for an overload where each parameter type exactly matches the argument type.
2. Subtype matching: If no exact match, TypeScript looks for overloads where argument types are subtypes of parameter types.
3. Order matters: Overloads are checked in the order they're declared. The first matching overload is used.
4. Contextual typing: In some cases (like callbacks), TypeScript uses the expected return type to help choose an overload.
### Common Pitfalls with Library Functions
React.createElement:
// React has specific overloads for intrinsic elements
const element1 = React.createElement("div"); // Works
const element2 = React.createElement("custom-component"); // Works
const element3 = React.createElement(Math.random() > 0.5 ? "div" : "span"); // Error!Array methods:
// Array.prototype.map has overloads for different callback signatures
const arr = [1, 2, 3];
arr.map(x => x * 2); // Works
arr.map((x, i) => x * i); // Works
arr.map((x, i, a) => x * a.length); // Works
// But TypeScript can get confused with complex callback types
const callback: ((x: number) => number) | ((x: number, i: number) => number) =
Math.random() > 0.5 ? (x) => x * 2 : (x, i) => x * i;
arr.map(callback); // Error: No overload matches this call### Generic Overloads
Generic overloads can be particularly tricky:
function merge<T>(obj1: T, obj2: T): T;
function merge<T, U>(obj1: T, obj2: U): T & U;
function merge(obj1: any, obj2: any): any {
return { ...obj1, ...obj2 };
}
// Works - same type
merge({ a: 1 }, { a: 2 }); // Returns { a: 2 }
// Works - different types
merge({ a: 1 }, { b: 2 }); // Returns { a: 1, b: 2 }
// Error - TypeScript can't decide which overload
merge({ a: 1 }, Math.random() > 0.5 ? { a: 2 } : { b: 2 });### Using Conditional Types with Overloads
For complex scenarios, conditional types can sometimes replace overloads:
// Instead of multiple overloads:
function process(input: string): string;
function process(input: number): number;
function process(input: boolean): boolean;
// Use conditional type:
type ProcessResult<T> = T extends string ? string :
T extends number ? number :
T extends boolean ? boolean : never;
function process<T>(input: T): ProcessResult<T> {
// Implementation
return input as any;
}
const result1 = process("hello"); // string
const result2 = process(42); // number
const result3 = process(true); // boolean### Debugging Overload Errors
Use TypeScript's compiler flags to debug:
# Show detailed type information
npx tsc --noEmit --explainFiles
# Or add this to tsconfig.json
{
"compilerOptions": {
"diagnostics": true,
"extendedDiagnostics": true
}
}The output will show which overloads were considered and why each was rejected.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript