为什么 Typescript 期望 fetch() 的“body”属性为 ReadableStream<Uint8Array>?

Leo*_*ang 14 javascript typescript

  const request: RequestInfo = {
    method,
    cache,
    redirect,
    headers: {} as Headers,
    body: null as string | null,
  };

  ...

  fetch(url, request);
Run Code Online (Sandbox Code Playgroud)

有了上面的内容,我得到:

Type 'string | null' is not assignable to type 'ReadableStream<Uint8Array> | null'.
  Type 'string' is not assignable to type 'ReadableStream<Uint8Array> | null'.
Run Code Online (Sandbox Code Playgroud)

在TS的类型声明中,有:

interface RequestInit {
    /**
     * A BodyInit object or null to set request's body.
     */
    body?: BodyInit | null;
}

type BodyInit = Blob | BufferSource | FormData | URLSearchParams | ReadableStream<Uint8Array> | string;
Run Code Online (Sandbox Code Playgroud)

为何期待ReadableStream<Uint8Array>

Kai*_*ido 6

不确定完全理解您的实际问题,但让我们回答这两种可能性。

该类型是用于RequestRequestInfo实例的类型,例如

const request: RequestInfo = new Request(url, requestInit);
Run Code Online (Sandbox Code Playgroud)

您正在创建的对象实际上是 的requestInit第二个参数fetch,为此您需要使用RequestInit类型。

const requestInit: RequestInit = {
  method,
  cache,
  redirect,
  headers: {} as Headers,
  body: null as string | null,
};
...
fetch(url, requestInit);
Run Code Online (Sandbox Code Playgroud)

现在,如果您想知道为什么RequestInit'sBodyInit成员说它可以是 a ReadablStream<Uint8Array>,那是因为根据规范它可以,即使还没有浏览器支持它并且规范还不是真正的防弹


Ale*_*hin 2

您显示的定义不太正确,您显示RequestInit,不是RequestInfo。我所拥有的(以及我在带有 TS 定义的微软页面上看到的)是这样的

type RequestInfo = Request | string
Run Code Online (Sandbox Code Playgroud)
interface Request extends Body {
  // No definition for `body` here
  // ...
}
Run Code Online (Sandbox Code Playgroud)
interface Body {
  readonly body: ReadableStream<Uint8Array> | null
  // ...
}
Run Code Online (Sandbox Code Playgroud)

所以很清楚,为什么编译器会抱怨。但我不清楚为什么定义是这样的,因为我确信它可以作为string请求body传递。我认为你必须将其转换为可读流:

body: 'string' as unknown as ReadableStream<Uint8Array>
Run Code Online (Sandbox Code Playgroud)

或者直接将其转换为any,因为这种类型转换相当长。我认为转换 to 不会any在这里造成任何混乱、错误或问题