You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript无法正确推断函数返回类型,求解决方案

解决API调用返回类型不匹配问题

问题场景

现有后端API调用函数loginCreate,定义如下:

loginCreate: (data: AuthenticationRequest, params: RequestParams = {}) =>
  this.request<AuthenticationResponse, IReason[]>({
    path: `/login`,
    method: "POST",
    body: data,
    secure: true,
    type: ContentType.Json,
    format: "json",
    ...params,
  })

该函数位于类库的Api类中,类库导出方式:

import * as AccountApi from "./lib/api.account";

export { AccountApi };

实际应用中通过accountApiStore实例化:

import { AccountApi } from "@central/api";

export default function accountApiStore(authToken?: string) {
  if (authToken) {
    return new AccountApi.Api({
      baseUrl: process.env.ACCOUNT_HOST,
      securityWorker: () => ({
        headers: { Authorization: `Bearer ${authToken}` }
      })
    });
  } else {
    return new AccountApi.Api({
      baseUrl: process.env.ACCOUNT_HOST
    });
  }
}

调用代码如下,但signing变量无法获取期望的AccountApi.HttpResponse<AccountApi.AuthenticationResponse, AccountApi.IReason[]>类型:

const signing = await accountApiStore()
    .login.loginCreate({
      username,
      password,
    })
    .catch((e) => e);

if (!signing.ok) {
  const res = await signing.json();
  return json(
    {
      errors: { username: res[0]?.message ?? "Invalid username or password" },
    },
    { status: 401 },
  );
}

问题原因

  1. 链式catch破坏类型推断:.catch((e) => e)会把Promise的返回类型改为loginCreate返回类型与catch回调返回值类型的联合类型,TypeScript无法确定signing的具体类型,自然无法匹配期望的HttpResponse类型。
  2. accountApiStore未明确返回类型:尽管函数返回的是AccountApi.Api实例,但分支逻辑可能导致TypeScript自动推断出现偏差,打断后续调用的类型链。

解决方案

方案1:改用try/catch结构(推荐)

移除链式catch,用try/catch捕获错误,让signing保留完整的HttpResponse类型:

try {
  const signing = await accountApiStore().login.loginCreate({
    username,
    password,
  });
  
  // 此处signing类型为期望的AccountApi.HttpResponse<...>
  if (!signing.ok) {
    const res = await signing.json();
    return json(
      {
        errors: { username: res[0]?.message ?? "Invalid username or password" },
      },
      { status: 401 },
    );
  }
  // 处理请求成功逻辑
} catch (e) {
  // 处理网络错误、请求超时等异常情况
  return json(
    { errors: { username: "Request failed" } },
    { status: 500 },
  );
}

方案2:明确accountApiStore的返回类型

给accountApiStore添加明确的返回类型,确保TypeScript能正确推断后续调用的类型:

import { AccountApi } from "@central/api";

export default function accountApiStore(authToken?: string): AccountApi.Api {
  if (authToken) {
    return new AccountApi.Api({
      baseUrl: process.env.ACCOUNT_HOST,
      securityWorker: () => ({
        headers: { Authorization: `Bearer ${authToken}` }
      })
    });
  } else {
    return new AccountApi.Api({
      baseUrl: process.env.ACCOUNT_HOST
    });
  }
}

如果坚持使用链式catch,需让catch返回值类型与HttpResponse兼容(不推荐直接用类型断言,会丢失类型安全):

const signing = await accountApiStore()
  .login.loginCreate({ username, password })
  .catch((e): AccountApi.HttpResponse<AccountApi.AuthenticationResponse, AccountApi.IReason[]> => {
    // 将错误转换为符合HttpResponse结构的对象
    return { ok: false, json: async () => [{ message: e.message || "Request failed" }] };
  });

内容的提问来源于stack exchange,提问作者Shabbir Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:03:26