TypeScript: условно объявить тип возвращаемого значения функции - PullRequest
0 голосов
/ 06 ноября 2018

Я пишу приложение React с использованием TypeScript.

Я написал оболочку для функции, которая выполняет вызов 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 голосов
/ 06 ноября 2018

Вы можете использовать перегрузки для правильного ввода функции.

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
0 голосов
/ 06 ноября 2018

Вы можете объявить перегрузки функции :

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>;
}
...