Skip to content

Missing overloads in FormData type definition #5934

@mattjohnsonpint

Description

@mattjohnsonpint

The standard FormData interface from TypeScript's lib.dom.d.ts is as follows:

interface FormData {
    append(name: string, value: string | Blob): void;
    append(name: string, value: string): void;
    append(name: string, blobValue: Blob, filename?: string): void;
    delete(name: string): void;
    get(name: string): FormDataEntryValue | null;
    getAll(name: string): FormDataEntryValue[];
    has(name: string): boolean;
    set(name: string, value: string | Blob): void;
    set(name: string, value: string): void;
    set(name: string, blobValue: Blob, filename?: string): void;
    forEach(callbackfn: (value: FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
}

The Cloudflare Workers implementation has this definition:

declare class FormData {
  constructor();
  append(name: string, value: string): void;
  append(name: string, value: Blob, filename?: string): void;
  delete(name: string): void;
  get(name: string): (File | string) | null;
  getAll(name: string): (File | string)[];
  has(name: string): boolean;
  set(name: string, value: string): void;
  set(name: string, value: Blob, filename?: string): void;
  entries(): IterableIterator<[key: string, value: File | string]>;
  keys(): IterableIterator<string>;
  values(): IterableIterator<File | string>;
  forEach<This = unknown>(
    callback: (
      this: This,
      value: File | string,
      key: string,
      parent: FormData,
    ) => void,
    thisArg?: This,
  ): void;
  [Symbol.iterator](): IterableIterator<[key: string, value: File | string]>;
}

As you can see, the append and set methods have overloads that are missing. Specifically:

    append(name: string, value: string | Blob): void;
    set(name: string, value: string | Blob): void;

Because these are missing, it can lead to compiler errors in user code. Consider:

if (typeof value === 'string') {
  data.append(key, value);  // ✅ value is string
} else if (value instanceof Blob) {
  data.append(key, value);  // ✅ value is Blob
}

That code compiles with the current definitions, but if the user tries to combine these, and is compiling with TypeScript strict mode settings, it fails:

if (typeof value === 'string' || value instanceof Blob) {
  data.append(key, value);  // ❌ TS2769
}
TS2769: No overload matches this call.

I encountered this error myself while trying to compile a project that uses @cloudflare/workers-types and a Typescript OpenAPI client generated from @hey-api/openapi-ts. You can see the pattern I described in one of their sample projects.

While it might be tempting to have @hey-api/openapi-ts work around this by splitting up the if statements, it would seem the proper fix is to add the overloads to @cloudflare/workers-types since they're indeed present in the normal definition. I can imagine many other projects could hit on this same issue.

Metadata

Metadata

Labels

typesRelated to @cloudflare/workers-types

Type

No type

Projects

Status

Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions