Skip to main content

TypeScript "No overload matches this call."

· 15 min read

This is normally an easy problem to fix. However, when it isn't easily fixed, trying to find the solution is difficult because the cause is typically not obvious.

TL;DR

This example here is one manifestation of such problems seen with TypeScript. Here, the problem occurs when FormData is used together with Object.fromEntries. E.g.

const form = evt.target as HTMLFormElement;
const formData = new FormData(form);
const data = Object.fromEntries(formData);

The IDE shows a wriggly line on formData with the following message:

No overload matches this call.
Overload 1 of 2, '(entries: Iterable<readonly [PropertyKey, any]>): { [k: string]: any; }', gave the following error.
Argument of type 'FormData' is not assignable to parameter of type 'Iterable<readonly [PropertyKey, any]>'.
Property '[Symbol.iterator]' is missing in type 'FormData' but required in type 'Iterable<readonly [PropertyKey, any]>'

No overload matches this call

Two things to check:

  1. Ensure that in tsconfig.json, the lib option contains minimally these two values in the array: DOM and DOM.Iterable (case-insensitive).
  2. If the tsconfig.json file contains the references option, check the lib option in the locations specified under references as well.

Introduction

TypeScript is a language that is based on JavaScript. Its website says that it is "JavaScript with syntax for types".

Indeed, after switching to use TypeScript, I've had the number of runtime issues reduced drastically compared to using JavaScript.

JavaScript has gained widespread adoption due in large part to the ease in which beginning developers can get started. The popularity also meant that different browsers have different JavaScript runtimes that support different versions of the language (though that's less of a problem nowadays since many have chosen to use the Chromium base). There are also various Web APIs that are implemented in JavaScript.

This wide adoption truly speaks for the flexibility of the language but because it is so open, it can be difficult to identify exactly which API and properties/functions are available.

This is where TypeScript benefits the developer greatly. Its typed nature means that integrated development environments (IDEs) can expose productivity enhancements such as code hints and autocompletion.

What's the issue?

For TypeScript to support the differing levels of the specification as well as the myriad libraries that are now available in JavaScript, it requires the use of a config file that is named tsconfig.json which is typically found in the root of the source project folder.

Learning all the options in tsconfig is an endeavour in and of itself.

I'd bet that most TypeScript developers (like, the overwhelming majority), myself included, know the syntax well, but not the configuration of tsconfig. In our defence, it is rare that tsconfig.json ever needs to be modified in the lifetime of a project once it is set up.

Having the correct options set will yield huge productivity benefits for the developer. Conversely, a wrongly configured file can create unexpected headaches.

One common problem is the error hints shown in the IDE.

Problem 1

I have two machines, one Linux and one MacOS (M1), that I develop on.

With the same codebase on one machine, everything works fine. When I check out the repository on the other machine, I see this wriggly line error in VS Code.

Missing repeat function

The first thought that comes to mind is that there must be some issues with tsconfig.json. It's not a pleasant thought. Trying to fix issues with tsconfig is a trial-and-error most of the time.

Luckily, the cause of the error is sometimes very simple. In this case, the dependencies have not been installed. This is indicated by the wrigglies on the import statements like so:

Missing imports

Errors on all the import statements of npm packages mean that the dependencies have not been installed yet. In this case, the resolution is to simply install the dependencies first.

Solution to problem 1

npm install

tip

Install dependencies as the first resolution.

When you are stuck on some problem it can be easy to forget to install the dependencies on a freshly checked out codebase.

Furthermore, if there are no import statements in the file with the error, it is even less obvious.

This is why I've adopted the heuristic of always running npm install/pnpm install first.

Problem 2

I am working on two TypeScript projects - one is a Next.js project, and the other is a codebase for a Chrome extension.

In both projects, I have the following code:

const form = evt.target as HTMLFormElement;
const formData = new FormData(form);
const data = Object.fromEntries(formData);

The code looks fine in the Next.js project.

But, in the Chrome extension project, the IDE complains:

No overload matches this call

Now, this happens after installing the dependencies so it's no longer just an easy fix of installing the dependencies.

Back to basics then. So the error says that Argument of type 'FormData' is not assignable to parameter of type 'Iterable<readonly [PropertyKey, any]>'.

This seems to suggest that the same FormData class in the extension codebase is of a different version from that in the Next.js codebase. I'm guessing this has to do with the version of TypeScript target or library specified in tsconfig.json

ProjectOptionValue
Next.jstarget"es5"
lib["dom", "dom.iterable", "esnext"]
Extensiontarget"ES2020"
lib["ES2020", "DOM", "DOM.Iterable", "WebWorker"]

Looking at target, the version stated in Next.js (es5) is even older than the version in the extension codebase (ES2020). target can't be the problem then.

How about lib? In Next.js we're seeing esnext whereas in the Chrome extension codebase, we're seeing ES2020. Could this be it?! esnext refers to the latest specifications so this should be the problem right?!

Attempted solution 1 to problem 2

So I changed lib. From this:

tsconfig.js (extension codebase)
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable", "WebWorker"],
"module": "ESNext",

to this:

tsconfig.js (extension codebase)
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ESNext", "DOM", "DOM.Iterable", "WebWorker"],
"module": "ESNext",

After saving this, the error persists.

"Okay," I'm thinking. "Let's just restart the TypeScript server for the change to take effect."

&quot;Restart TS Server&quot;

Nope. Error still shows in the IDE.

note

I've even tried variations like:

  • Removing DOM.Iterable, restarting TS Server, then adding back in.
  • Place DOM.Iterable last in the array.
  • Change to lowercase and place dom.iterable first in the array.

And restarting TS Server after every change.

I didn't think that these will fix the problems but I had to try them when I was running out of ideas.

Attempted solution 2 to problem 2

Alright. Let's inspect the other options in tsconfig.json.

OptionNext.js ValueExtension Value
allowJstruenot set
skipLibChecktruetrue
stricttruetrue
forceConsistentCasingInFileNamestruenot set
noEmittruetrue
esModuleInteroptruenot set
moduleesnextESNext
moduleResolutionnodebundler
resolveJsonModuletruetrue
isolatedModulestruetrue
jsxpreservereact-jsx
incrementaltruenot set
paths{ "~src/*": ["./src/*"], "~public/*": ["./public/*"] }not set

Nothing stands out as to what could be the cause. So I copied the values over to make the options identical in both projects. No bueno.

Okay. Since the configurations are all the same already, let's take a closer look at the problem. It says that Property '[Symbol.iterator]' is missing in type 'FormData' but required in type 'Iterable<readonly [PropertyKey, any]>'. So this means that the FormData class used in the extension codebase does not have the properties to be Iterable. Why?

Attempted solution 3 to problem 2

Ctrl/Cmd-clicking on the FormData class reveals two differences:

Node.js code Code in Node.js

extension code Code in extension codebase

In the Node.js codebase, there is a reference to lib.dom.iterable.d.ts whereas in the extension codebase, this is not present.

This makes sense since what is missing is the iterable property of FormData.

The second difference is that the Node.js codebase references @types+react@18.2.73 whereas the extension codebase references @types+react@18.2.48.

Could that be it?

Let's compare the package.json files of both codebases:

CodebaseDependency
Next.js"@types/react": "^18.2.12",
Extension"@types/react": "^18.2.43",
note

At this point it is worth highlighting that the codebases are using pnpm and not npm.

So there is a disparity between the versions. I'm not exactly sure what is going on, so I'm installing the latest version of @types/react for the extension codebase:

pnpm add -D @types/react@latest

After restarting the TS Server, the wriggly is still there. 😡

Attempted solution 4 to problem 2 - StackOverflow

Next, I took to StackOverflow (being sceptical that AI could solve this problem).

This answer that I've found is answering the question why VS Code is not honouring the options in tsconfig.json. I'm not entirely sure this is the same problem, but at this stage, I'm willing to try anything.

So I added "typescript.tsdk": "node_modules/typescript/lib" to .vscode/settings.json.

After restarting TS Server, the problem persists. 🤬

Attempted solution 5 to problem 2 - ChatGPT

Alright. Next up, AI. Let's see what this jobs-killer, revolutionary technology can do in this case.

Me:

VS Code is not reading lib.dom.iterable.d.ts for my TypeScript project. How can I solve this problem?

ChatGPT gave a few suggestions. Let's break them down:

ChatGPT:

To resolve the issue of VS Code not reading lib.dom.iterable.d.ts for your TypeScript project, follow these steps:

1. Check TypeScript Version:

Ensure you are using an up-to-date version of TypeScript. Update TypeScript globally and locally in your project if necessary.

npm install -g typescript
npm install typescript --save-dev
CodebaseDependency
Next.js"typescript": "^5.1.3",
Extension"typescript": "^5.2.2"

Huh. The extension is already using a newer version of TypeScript.

ChatGPT:

2. Update VS Code:

Make sure you are using the latest version of Visual Studio Code. Updates often include fixes for issues like this.

VS Code version for LinuxVS Code version for MacOS

Well, I'm already on the latest version on both of my machines, and the same problem occurs on both of them.

ChatGPT:

3. Check tsconfig.json:

Ensure your tsconfig.json file includes the necessary library references. Your tsconfig.json should have a section like this:

{
"compilerOptions": {
"lib": ["dom", "es2015", "dom.iterable"]
}
}

This explicitly includes dom.iterable as part of the TypeScript compilation process.

Yes, that's the first thing I've checked. (See Attempted solution 1)

ChatGPT:

4. Ensure TypeScript is Correctly Configured in VS Code:

Sometimes, VS Code may use a different TypeScript version than the one installed in your project. To ensure VS Code uses the correct version:

  • Open the command palette (Ctrl+Shift+P or Cmd+Shift+P).
  • Type and select "TypeScript: Select TypeScript Version".
  • Choose "Use Workspace Version" to make sure it uses the TypeScript version specified in your project.

Non-starter. No such option.

Let's give it the benefit of the doubt - it might referring to a Workspace setting.

TypeScript

Oh! Tried this already. 😐

ChatGPT:

5. Reload VS Code Window:

After making changes to tsconfig.json, reload the VS Code window to ensure the new configuration is applied.

  • Open the command palette and type "Reload Window", then select it.

Reload VS Code? I had been using Windows in my previous life. Of course I had reloaded VS Code already.

ChatGPT:

6. Verify File Presence:

Ensure the lib.dom.iterable.d.ts file is present in the node_modules/typescript/lib directory. If it's missing, reinstall TypeScript:

npm install typescript --save-dev

lib.dom.iterable.d.ts

Yup it's there. And still using the setting "typescript.tsdk": "node_modules/typescript/lib".

What if I remove this line? Problem's still there. 😤

ChatGPT:

7. Check for Extensions:

Some extensions can interfere with TypeScript's configuration. Try disabling extensions one by one to see if any are causing the issue.

Not useful. I'm using the same editor with the same set of extensions on two projects giving two different behaviour.

ChatGPT:

8. Clear VS Code Cache:

Sometimes, clearing the TypeScript server's cache can resolve issues. You can do this by:

  • Deleting the .vscode directory in your project.
  • Restarting VS Code.

By following these steps, you should be able to resolve the issue of VS Code not reading lib.dom.iterable.d.ts in your TypeScript project.

Restarted already lah!

Attempted solution 6 to problem 2 - Meta AI

Me:

VS Code is not reading lib.dom.iterable.d.ts for my TypeScript project. How can I solve this problem?

Meta AI:

Here are some steps you can take to troubleshoot why VS Code is not reading lib.dom.iterable.d.ts for your TypeScript project ¹ ² ³ ⁴:

  • Ensure that your .d.ts file is open in your VS Code window for the changes to take effect.
  • Make sure your tsconfig.json file is in the root directory, as VS Code will only read files in this directory.
  • Try running the command "Reload Window" to see if this resolves the issue.
  • Check that your .d.ts file is in the correct directory and that the file path is correct in your tsconfig.json file.
  • Make sure that you are not skipping the library check in your tsconfig.json file by setting "skipLibCheck": false.
  • If you are still having trouble, try restarting the TypeScript server or VS Code to see if this resolves the issue.

The only things that are new as suggested by Meta AI are the "Reload Window" command and setting "skipLibCheck": false. Both of which didn't solve the problem.

lib.dom.iterable.d.ts not read by vs code

First result from StackOverflow had many of the attempted solutions listed.

Time for something more drastic. I closed the editor, removed the entire node_modules directory, ran pnpm install, then started the editor back up again.

No luck 🫤

Attempted solution 8 to problem 2 - include

This is the "I'll try anything" stage.

The include field in tsconfig.json did not specify the .ts and .tsx files in the extension codebase. Maybe the configuration is sensitive that way?

OptionValue
Original["src"]
Changed["**/*.ts", "**/*.tsx"]

Result: Nope. ❌

Attempted solution 9 to problem 2 - exclude

Another "I'll try anything" attempt.

I noticed that in the Next.js project, the node_modules directory was excluded.

ProjectOptionValue
Next.js'exclude'["node_modules"]
Extension'exclude'"exclude": ["src/**__tests__/*"]

So in this attempt, I'm adding node_modules to exclude:

"exclude": ["src/**__tests__/*", "node_modules"]

Of course this didn't work — I don't expect it to. 🙄

Attempted solution 10 to problem 2 - project references

Grasping at straws now.

I noticed another difference between the two tsconfig.json files.

ProjectOptionValue
Next.jsreferencesnot set
Extensionreferences[{ "path": "./tsconfig.node.json" }]

The tsconfig.node.json file in the extension codebase looks like this:

{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"paths": {
"~src/*": ["./src/*"],
"~assets/*": ["./src/assets/*"],
"~pages/*": ["./src/pages/*"],
"~public/*": ["./src/public/*"]
},
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts", "src", "scripts", "plugins"]
}

Huh. There's no lib option here. Could that be it? What if I added lib to this config file?

{
"compilerOptions": {
"composite": true,
"lib": ["DOM", "DOM.Iterable"],
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"paths": {
"~src/*": ["./src/*"],
"~assets/*": ["./src/assets/*"],
"~pages/*": ["./src/pages/*"],
"~public/*": ["./src/public/*"]
},
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts", "src", "scripts", "plugins"]
}
success

😱 🎊 🎉

Took me four hours on a Sunday to figure it out and to write this post but I got it!

For whatever reason, the referenced project (tsconfig.node.json) is the one that VS Code is taking cue from instead of the one at the root (tsconfig.json).

No need for all the changes described in attempted solutions 1 to 8. All that's needed is just this one line "lib": ["DOM", "DOM.Iterable"] in the right file.

I had read project references before but never understood it well enough to internalise it. It's probably something I will procrastinate again until the next problem with tsconfig crops up. Again.

note

On a related note, there is also jsconfig.json that is essentially tsconfig.json with "allowJs": true