The browser polyfill conditionally replaces the native FormData implementation with an enhanced version that provides full HTML5 specification support. It automatically patches browser APIs (XMLHttpRequest, fetch, sendBeacon) to seamlessly handle FormData serialization without requiring code changes.
The polyfill replaces the global FormData constructor when the native implementation lacks complete specification support.
/**
* Enhanced FormData implementation that replaces native FormData
* @param form - Optional HTMLFormElement to populate from
*/
class FormData {
constructor(form?: HTMLFormElement);
}Usage Example:
import "formdata-polyfill";
// Automatically uses enhanced FormData
const fd = new FormData();
// Can also construct from HTML form
const form = document.getElementById("myForm");
const formData = new FormData(form);When constructed with an HTMLFormElement, the FormData instance is automatically populated with the form's field values.
Usage Example:
// HTML form
// <form id="userForm">
// <input name="username" value="john" />
// <input name="email" value="john@example.com" />
// <input type="file" name="avatar" />
// <select name="country">
// <option value="us" selected>United States</option>
// </select>
// <input type="checkbox" name="newsletter" checked />
// </form>
const form = document.getElementById("userForm");
const fd = new FormData(form);
// FormData is now populated with:
// - username: "john"
// - email: "john@example.com"
// - avatar: File object (if file selected)
// - country: "us"
// - newsletter: "on" (if checked)All standard HTML5 FormData methods are fully supported with enhanced behavior.
/**
* Standard FormData interface methods
*/
append(name: string, value: string | Blob | File, filename?: string): void;
delete(name: string): void;
get(name: string): string | File | null;
getAll(name: string): (string | File)[];
has(name: string): boolean;
set(name: string, value: string | Blob | File, filename?: string): void;
forEach(callback: (value: string | File, name: string, formData: FormData) => void, thisArg?: any): void;
entries(): Iterator<[string, string | File]>;
keys(): Iterator<string>;
values(): Iterator<string | File>;
[Symbol.iterator](): Iterator<[string, string | File]>;Usage Examples:
import "formdata-polyfill";
const fd = new FormData();
fd.append("name", "Alice");
fd.set("email", "alice@example.com");
// Iterator support works in all browsers
for (const [key, value] of fd) {
console.log(`${key}: ${value}`);
}
// All methods work consistently
console.log(fd.has("name")); // true
console.log(fd.get("email")); // "alice@example.com"Converts the enhanced FormData instance to a native FormData object (browser-specific).
/**
* Converts to native FormData instance (browser only)
* @returns Native FormData object
*/
_asNative(): FormData;Usage Example:
const fd = new FormData();
fd.append("test", "value");
// Get native FormData (for specific APIs that require it)
const nativeFormData = fd._asNative();Converts the FormData instance to a properly encoded multipart/form-data Blob.
/**
* Converts FormData to multipart/form-data Blob (browser only)
* @returns Blob with proper multipart encoding
*/
_blob(): Blob;Usage Example:
const fd = new FormData();
fd.append("name", "John");
fd.append("file", new File(["content"], "test.txt"));
// Convert to blob manually (usually not needed due to automatic patching)
const blob = fd._blob();
console.log(blob.type); // "multipart/form-data; boundary=----formdata-polyfill-..."The polyfill automatically patches XMLHttpRequest.prototype.send to handle FormData serialization transparently.
// Automatically patched - no API changes needed
// Original: XMLHttpRequest.prototype.send(data)
// Enhanced: Automatically converts FormData to Blob when neededUsage Example:
import "formdata-polyfill";
const xhr = new XMLHttpRequest();
const fd = new FormData();
fd.append("data", "test");
xhr.open("POST", "/upload");
// FormData is automatically converted to Blob with proper Content-Type
xhr.send(fd);The polyfill automatically patches the global fetch function to handle FormData bodies correctly.
// Automatically patched - no API changes needed
// Original: fetch(input, init)
// Enhanced: Automatically converts FormData in request body to BlobUsage Examples:
import "formdata-polyfill";
const fd = new FormData();
fd.append("username", "john");
fd.append("avatar", fileInput.files[0]);
// FormData is automatically handled
fetch("/api/users", {
method: "POST",
body: fd, // Automatically converted to proper multipart Blob
});
// Also works with Request constructor workaround
const request = new Request("/api/upload", {
method: "POST",
body: fd._blob ? fd._blob() : fd, // Manual fallback for Request constructor
});
fetch(request);The polyfill patches navigator.sendBeacon to use native FormData for optimal browser compatibility.
// Automatically patched - no API changes needed
// Original: navigator.sendBeacon(url, data)
// Enhanced: Converts FormData to native format for sendBeaconUsage Example:
import "formdata-polyfill";
const fd = new FormData();
fd.append("event", "page_exit");
fd.append("timestamp", Date.now().toString());
// FormData is automatically converted to native format
navigator.sendBeacon("/analytics", fd);The polyfill provides a File constructor for browsers that don't support it natively.
/**
* File constructor polyfill (when needed)
* @param fileBits - Array of data chunks
* @param fileName - Name of the file
* @param options - File options
*/
class File extends Blob {
constructor(fileBits: BlobPart[], fileName: string, options?: FilePropertyBag);
readonly name: string;
readonly lastModified: number;
}Usage Example:
import "formdata-polyfill";
// File constructor works in all browsers
const file = new File(["Hello, World!"], "greeting.txt", {
type: "text/plain",
lastModified: Date.now(),
});
const fd = new FormData();
fd.append("document", file);Proper string tag support for FormData instances.
/**
* String tag for Object.prototype.toString()
*/
[Symbol.toStringTag]: "FormData";Usage Example:
import "formdata-polyfill";
const fd = new FormData();
console.log(Object.prototype.toString.call(fd)); // "[object FormData]"
console.log(fd.toString()); // "[object FormData]"The polyfill includes several compatibility enhancements for older browsers:
Element.prototype.matches for older browsersDetection and Conditional Loading:
// The polyfill only activates when needed
if (typeof Blob !== 'undefined' && (typeof FormData === 'undefined' || !FormData.prototype.keys)) {
// Polyfill activates automatically
}Browser Compatibility:
The polyfill provides support for:
append() with filename parameterdelete(), get(), getAll(), has(), set() methodsentries(), keys(), values() iteratorsfor...of loop support