TypeScript:有条件地声明函数的 return 类型

TypeScript: Conditionally declare the return type of a function

我正在使用 TypeScript 编写 React 应用程序。

我已经为进行 API 调用的函数编写了包装器:

import { ROUTE_CANDIDATES, ROUTE_TWIG_PICK } from "../../../config/constants/routes";
import { pickSchema } from "../../../config/schemas/picks";
import { PickCreateBulkResponse, PickCreateUpdateResponse } from "../../../config/types";
import { postRequest, putRequest } from "../../utils/serverRequests";

interface PickJSON {
  candidate: string;
  picked_int_choice: string;
}

const pickListSchema = [pickSchema];

export const postPickCreate = (
  body: PickJSON | PickJSON[]
): Promise<PickCreateUpdateResponse | PickCreateBulkResponse> => {
  if (Array.isArray(body)) {
    return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as Promise<
      PickCreateBulkResponse
    >;
  } else {
    return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as Promise<
      PickCreateUpdateResponse
    >;
  }
};

如您所见,我正在尝试动态断言正确的响应类型。这意味着如果该函数与数组一起使用,它应该 return a Promise<PickCreateBuldResponse>,而如果它与单个对象一起使用,它应该 return Promise<PickCreateUpdateResponse>。我怎样才能让 TypeScript 知道它 return 是什么?正如您在上面看到的,我尝试使用 as,但这不起作用。

您可以声明function overloads:

export function postPickCreate(body: PickJSON): Promise<PickCreateUpdateResponse>
export function postPickCreate(body: PickJSON[]): Promise<PickCreateBulkResponse>
export function postPickCreate(body: PickJSON | PickJSON[]):
    Promise<PickCreateUpdateResponse | PickCreateBulkResponse> {

    if (Array.isArray(body)) {
        return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as
            Promise<PickCreateBulkResponse>;
    } else {
        return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as
            Promise<PickCreateUpdateResponse>;
    }
}

但是,由于在您的情况下您已经在设计时知道值的类型并且 TypeScript 会为您进行类型检查,因此最好的方法可能是简单地分离您的函数。这就是您在 if 块中的函数内部实际执行的操作:

export function postPickCreate(body: PickJSON): Promise<PickCreateUpdateResponse> {
    return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as
        Promise<PickCreateUpdateResponse>;
}

export function postPickCreateRange(body: PickJSON[]): Promise<PickCreateBulkResponse> {
    return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as
        Promise<PickCreateBulkResponse>;
}

您可以使用 overloads 来正确输入函数。

interface Foo {}

interface BarMany { many: string; }
interface BarOne { one: string; }

interface BazFunc {
    (foo: Foo[]): BarMany;
    (foo: Foo): BarOne;
}

const baz: BazFunc = (foo) => {
    if(Array.isArray(foo)) {
    return { many: "flibble" };
  } else {
      return { one: "flibble" };
  }
};

var one = baz({});
var many = baz([]);

这是一个正在运行的 jsFiddle:https://jsfiddle.net/z4vo5u5d/22392/

并且输出:

one - One: flibble, Many: undefined
many - One: undefined, Many: flibble