Quick answer
Your arguments match none of the function's overload signatures. To fix it:
- Find the overload you meant to call in the error output, and read only its sub-error.
- That sub-error names the argument that doesn't match and the type it expected — fix that one argument.
- Passing a union (
string | number)? Narrow it withtypeofbefore the call. - An options object? The mismatch is usually one wrong or extra property.
The exact error string
function toArray(x: string): string[];
function toArray(x: number): number[];
function toArray<T>(x: T): T[] {
return [x];
}
const value: string | number = getValue();
toArray(value);
// error TS2769: No overload matches this call.
// Overload 1 of 2, '(x: string): string[]', gave the following error.
// Argument of type 'string | number' is not assignable to parameter of type 'string'.
// Overload 2 of 2, '(x: number): number[]', gave the following error.
// Argument of type 'string | number' is not assignable to parameter of type 'number'.
An overloaded function has more than one call signature. When you call it, TypeScript tries each signature in order and, if none accepts your exact arguments, reports TS2769 and prints why each one was rejected. The error looks intimidating because it dumps every failed overload — but the trick is to ignore most of it and read only the overload you actually intended to call. Note that the implementation signature above is generic (<T>) even though the two public overloads only allow string or number — that's normal, not a mistake: the overload signatures are the restricted public API callers see, while the implementation signature can be broader internally. Callers never see or call the implementation signature directly, so it doesn't loosen what's actually allowed at a call site.
How overload resolution works (and how to read the error)
TypeScript reports every rejected overload, but you only need the sub-error for the signature you actually intended — that line names the argument to fix.
Fix 1: narrow a union argument before the call
In the example above, value is string | number. Overload 1 wants a string, overload 2 wants a number, and neither accepts the whole union — so the call fails even though every runtime value would be valid for some overload. Narrow it first:
if (typeof value === "string") {
toArray(value); // ✅ value is string here — overload 1 matches
} else {
toArray(value); // ✅ value is number here — overload 2 matches
}
Inside each branch the argument is a single concrete type, so exactly one overload applies and TS2769 disappears.
Fix 2: fix a wrong argument type
Often the mismatch is simpler — a value that's just the wrong type for the overload you wanted. This is the multi-overload cousin of TS2345. Read the sub-error for your intended overload and correct that argument:
// a real-world shape: an overloaded API client
declare function request(url: string, opts?: { method: "GET" }): Promise<Response>;
declare function request(url: string, opts: { method: "POST"; body: string }): Promise<Response>;
request("/api", { method: "POST", body: { id: 1 } });
// ❌ TS2769 — the POST overload wants body: string, you passed an object
request("/api", { method: "POST", body: JSON.stringify({ id: 1 }) });
// ✅ body is now a string — the POST overload matches
Passing raw objects where a serialized string is expected is a classic trigger here; when the target type is a string body, run the value through JSON stringify (or JSON.stringify) first.
Fix 3: an options object with a wrong or extra property
When overloads differ by the shape of an options object, a single bad property rejects every overload. The last overload's sub-error usually points right at it:
// ❌ 'responseType' has a typo'd value; no overload accepts "jsonn"
axiosLike.get("/users", { responseType: "jsonn" });
// ... Type '"jsonn"' is not assignable to type 'ResponseType'.
// ✅ correct the property value
axiosLike.get("/users", { responseType: "json" });
Excess-property checks make object literals especially strict here: an extra property that no overload declares is itself enough to cause TS2769, so also check for a stray or misnamed key, not just a wrong value.
Fix 4: wrong number of arguments
If your argument count matches no overload — too few required arguments, or more than any signature accepts — you get TS2769 as well. Compare your call against each signature's arity and pass the set of arguments one real overload declares.
Fix 5: a literal type got widened before the call
This one is confusing because, unlike Fix 1, there's no visible union anywhere in your code — the value just looks like it should match. The culprit is TypeScript's literal-widening rule: assigning a string literal to a let widens its type to the general string, discarding the specific literal:
function setStatus(status: "active"): void;
function setStatus(status: "inactive"): void;
let status = "active"; // widened to `string`, not the literal "active"
setStatus(status); // TS2769 — no overload accepts a plain string
Both overloads only accept a specific string literal, but status's inferred type is the wider string, and string isn't assignable to either literal type — so neither overload matches, even though the runtime value "active" is exactly what one overload wants. Fix it by preventing the widening, not by changing the value:
let status = "active" as const; // ✅ keeps the literal type "active"
// or:
let status: "active" | "inactive" = "active"; // ✅ explicit union annotation
// or, if the value never needs to be reassigned:
const status = "active"; // ✅ const infers the literal type directly
Diagnose this by checking the declaration, not the call: if the argument is declared with let and no type annotation, and every overload expects a specific literal, widening is very likely the cause.
Fix 6: the library's overloads changed after an upgrade
Sometimes none of the above applies because the code used to compile and nothing in your call site changed — only a dependency version did. A minor or major upgrade of a library can add, remove, or reshape its overload signatures, and existing calls that matched the old signatures stop matching the new ones. When TS2769 appears right after running npm update or bumping a version in package.json:
- Check the installed version of the package against the version your code was written for — a changelog or migration guide often documents the overload change directly.
- If you're unsure what changed, diff the relevant
.d.tsfile between the two versions innode_modules(or on a site like unpkg) to see the exact signature difference. - Update the call site to match the new signature — this is usually a small, mechanical change once you know what moved, rather than a sign your code was ever wrong.
Common React TS2769 cases
Two patterns produce a genuine TS2769 in React code specifically — both are argument-count or overload-selection failures, the same class of problem as Fix 4:
// too many arguments — same class as Fix 4
const [count, setCount] = useState(0, 10);
// TS2769: Expected 0-1 arguments, but got 2.
// no overload of useRef accepts this initial value's type
const ref = useRef<HTMLInputElement>("not a DOM node");
// TS2769: No overload matches this call.
useState only ever takes zero or one argument (the initial state); a second argument matches no overload, exactly like Fix 4. useRef<HTMLInputElement> is overloaded on the initial value's type, and a string doesn't satisfy any of them. Two other React errors get miscategorized as this one but aren't — worth knowing so you land on the right fix: passing the wrong value to a single-signature setter like useState(null) then setValue("hello") is TS2345, not TS2769 (there's only one signature, not several); and a bad JSX prop like <MyButton size="largee" /> is TS2322, since JSX props are checked as object-literal assignability, not function overload resolution.
What NOT to do
Casting the argument to any (toArray(value as any)) forces an overload to accept it and makes the red squiggle vanish — but it also turns off checking for that argument, so a genuinely wrong call sails through to runtime. Narrow the union, fix the type, or correct the argument count instead. Reach for a cast only when you've confirmed at runtime that the value really is valid for the overload you're calling.
Debugging checklist
- ✓ Identify which overload you meant to call, and read only that sub-error
- ✓ The sub-error names one argument and the type it expected — fix that argument
- ✓ Union argument (
string | number)? Narrow withtypeof/ a type guard first - ✓ Options object? Look for a wrong value or an extra/misnamed property
- ✓ Count mismatch? Match your argument count to a real signature's arity
- ✓ Value declared with
let, overloads expect a specific literal? Check for widening — useas constor an explicit union type - ✓ Started right after a dependency upgrade? Diff the library's
.d.tsfor a changed overload - ✓ Don't cast to
anyto silence it — that ships the real bug to runtime
Frequently Asked Questions
What does TS2769: No overload matches this call mean?
The function you called is declared with multiple overload signatures, and the arguments you passed don't fully match any single one of them. TypeScript then reports the call as unresolvable and, underneath, lists the reason each overload was rejected. It's not saying the function is wrong — it's saying your specific combination of argument types or count doesn't line up with any allowed shape.
How do I read the 'Overload N of M gave the following error' output?
TypeScript prints one sub-error per overload it tried: “Overload 1 of 3 ... Argument of type X is not assignable to parameter of type Y.” Find the overload you actually intended to call, ignore the others, and read only its sub-error — that line tells you exactly which argument doesn't match and what type it expected. Fixing that one argument usually resolves the whole TS2769.
Why does it happen when I pass a union type as an argument?
Overload resolution needs one overload to accept the entire argument type. If your value is a union like string | number and each overload only accepts one member, none accepts the whole union, so TS2769 fires even though every possible runtime value would be valid for some overload. Narrow the union first with a typeof or type guard so that at the call site the argument is a single concrete type, then call inside each branch.
Why do I get TS2769 on an options or config object?
When a function is overloaded on the shape of an options object, an object with an extra, missing, or mistyped property matches no overload. Read the last overload's sub-error — it usually points at the offending property, for example ‘responseType is not assignable’ — and fix that property's value or type. Excess-property checks on object literals are a frequent trigger here.
Is casting the argument to any a good fix for TS2769?
No. Casting an argument to any forces one overload to accept it and silences TS2769, but it also disables checking for that argument, so a genuinely wrong call ships to runtime. Fix the real mismatch instead: correct the argument's type, narrow a union before the call, or adjust the argument count to match a real overload. Cast only as a last resort when you've verified the runtime value is actually valid.
How is TS2769 related to TS2345?
TS2345 (“Argument of type X is not assignable to parameter of type Y”) is the single-signature version: one function, one signature, one bad argument. TS2769 is the multi-signature version: the same kind of argument mismatch, but the function has several overloads, so TypeScript reports that none of them matched and nests a TS2345-style reason under each rejected overload. Read the nested reason for the overload you intended.
More TypeScript & JSON errors
Browse the full reference, or generate accurate interfaces from your JSON.