在 Typescript 中使用 fetch 进行数据转换

Using fetch in Typescript with data transformations

我正在尝试将 js 代码转换为 ts,并且我有这个:

function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then((res) => {
      return res.json().then((resJson: T) => ({
        ok: res.ok,
        status: res.status,
        body: resJson,
      }));
    })
    .then((res) => {
     if (res.ok) {
       return res.body;
     }
     return Promise.reject({
       status: res.status,
       message: res.body.message,
     });
    });
}

我不知道如何解决

的问题
message: res.body.message // Property 'message' does not exist on type 'T'

仅当 res.ok === false 时,我的正文响应才包含“消息”属性 作为可选内容。这个案子怎么破? 大概用量:

type ResBody = {
  success: boolean;
  message?: string;
  data?: string[];
};

api<ResBody>("https://example.com")
  .then(({ success, data }) => {
    console.log(success, data);
  })
  .catch((err) => {
    console.log(err.message, err.status)
  });

Promise 类型有一个泛型参数T,这样你就可以声明异步函数的return 类型。这允许您以类型安全的方式引用该 return 值。

您的第一个 then return 对象 body 分配了一个 T 类型的值,然后您的下一个 then 将其作为其对象res 输入。这意味着 res 被推断为具有 T 类型的 body。然后您引用 res.body.message,但您没有在哪里声明类型 T 是具有字段 message.

的类型

当您在 function api<T> 声明中声明泛型参数 T 时,您需要这样做,如下所示:

function api<T extends ResBody>(url: string): Promise<T> {
  return fetch(url)
    .then((res) => {
      return res.json().then((resJson: T) => ({
        ok: res.ok,
        status: res.status,
        body: resJson,
      }));
    })
    .then((res) => {
      if (res.ok) {
        return res.body;
      }
      return Promise.reject({
        status: res.status,
        message: res.body.message,
      });
    });
}

T extends ResBody 告诉 Typescript 通用类型 T,无论它最终是什么,都将是 ResBody 或其子类型,因此将有一个可选的 message 字段类型 string.

你可以比这更通用,即如果 T 可以是 任何 类型,其中包含 message 字段,如下所示:

function api<T extends {message?: string}>(url: string): Promise<T> {
  return fetch(url)
    .then((res) => {
      return res.json().then((resJson: T) => ({
        ok: res.ok,
        status: res.status,
        body: resJson,
      }));
    })
    .then((res) => {
     if (res.ok) {
       return res.body;
     }
     return Promise.reject({
       status: res.status,
       message: res.body.message,
     });
    });
}

T extends {message?: string} 告诉 Typescript 泛型类型 T,无论它最终是什么,都有一个类型为 string.

的可选 message 字段