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

时间:2018-11-06 08:35:56

标签: reactjs typescript typescript-typings typescript-types

我正在使用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
    >;
  }
};

如您所见,我正在尝试动态声明正确的响应类型。意味着如果该函数与数组一起使用,则应返回Promise<PickCreateBuldResponse>,而如果与单个对象一起使用,则应返回Promise<PickCreateUpdateResponse>。如何让TypeScript知道返回的内容?如您在上面看到的,我尝试使用as,但这是行不通的。

2 个答案:

答案 0 :(得分:5)

您可以声明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>;
}

答案 1 :(得分:0)

您可以使用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