Add a generic type argument to `fetch()` function and `Body` interface

Open
#458 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
32/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
typescript
Domain
tooling

Research direction

The issue names the WIDL definitions for Body, Request, Response, and GlobalFetch, but no source files or tests. Start by locating those definitions and learning how the generator represents generic interfaces and functions. Done means generated fetch types accept an optional generic argument, response.json() returns that type, and existing unparameterized usage remains compatible.

Written by the indexing model from the issue text.

Description

The generic type argument would add depth and consistency to the fetch types.

Expected behavior (example):

Generated definitions:

interface Body<T = any> {
    readonly bodyUsed: boolean;
    arrayBuffer(): Promise<ArrayBuffer>;
    blob(): Promise<Blob>;
    formData(): Promise<FormData>;
    json(): Promise<T>;
    text(): Promise<string>;
}

interface Request<T = any> extends Body<T> {...}
interface Response<T = any> extends Body<T> {...}
...

interface GlobalFetch {
    fetch<T>(input?: Request | string, init?: RequestInit): Promise<Response<T>>;
}

Usage with type:

type MyFetchResponse = { a: string, b: number };
fetch<MyFetchResponse>('https://someserver.com/get?a=string&b=number').then(response => {
  response.json().then(data => {
    // data is MyFetchResponse

    // Both of these are autocompleted at this point
    data.a
    data.b

    data.c //Error: Property 'c' does not exist on type MyFetchResponse
  })
})

Usage without types (same as current):

fetch('https://someserver.com/get?a=string&b=number').then(response => {
  response.json().then(data => {
    // data is any
    data.a
    data.b

    data.c //No error here
  })
})
Actual behavior:
fetch('https://someserver.com/get?a=string&b=number').then(response => {
  response.json().then(data => {
    // data is any
    data.a
    data.b

    data.c //No error here
  })
})
Motivation:

The proposed change would make the usage of fetch much more convenient in typed code without the need for unnecessary castings and overrides.

This change will not brake any other definitions relying on Body, Request and Response interfaces due to the use of optional generic arguments. Therefore, in current definitions, declare var a: Response will automatically evaluate to declare var a: Response<any> thus making the change backward-compatible.

P.S. Creating an issue instead of the pull request because I'm not familiar with WIDL syntax that's used here and I coudn't find any explanatory documentation on it.

Dominant language
TypeScript
Stars
740
Forks
474
Avg merge
2d 8h
Merged PRs (30d)
15

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/TypeScript-DOM-lib-generator

All issues in microsoft/TypeScript-DOM-lib-generator

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.