Как мы можем сделать аргумент внутренней функции необязательным в зависимости от аргумента внешней функции?

#typescript #react-redux #redux-toolkit

Вопрос:

Существует функция, которая возвращает другую. Я хочу сделать параметр внутренней функции необязательным, если присутствует параметр внешней функции, и обязательным в противном случае.

 function outer(a?: number) {
  // How can we make b here optional if a is present and mandatory otherwise?
  return function inner(b: number) {
    // some stuff
  };
}
 

Конечно, мы можем просто вернуть две функции с разными сигнатурами внутри внешней функции, но мне интересно, есть ли лучшее решение.

Обновить

Решение с перегрузкой функций работает для этого простого примера.

 function outer(a: number): (b?: number) => any;
function outer(a?: number): (b: number) => any;
function outer(a?: number) {
  return function inner(b?: number) {
    // some stuff
  };
}

outer(1)(2);
outer(1)();
outer()(1);
 

Как насчет реального примера с Redux:

 import { AsyncThunk, createAsyncThunk } from "@reduxjs/toolkit";

type RecipeGetter = () => string[];
type ThunkWithOptionalRecipeIds = AsyncThunk<
  Record<string, string>,
  string[] | undefined,
  Record<string, never>
>;
type ThunkWithRequiredRecipeIds = AsyncThunk<
  Record<string, string>,
  string[],
  Record<string, never>
>;

function getFetchRecipesByIdThunk(
  typePrefix: string,
  recipeIdGetter: RecipeGetter,
): ThunkWithOptionalRecipeIds;
function getFetchRecipesByIdThunk(
  typePrefix: string,
  recipeIdGetter?: RecipeGetter,
): ThunkWithRequiredRecipeIds;
function getFetchRecipesByIdThunk(
  typePrefix: string,
  recipeIdGetter?: RecipeGetter,
) {
  return createAsyncThunk(typePrefix, async (recipeId?: string[]) => {
    // some stuff
  }
}
 

Похоже, что здесь это не работает:
Скриншот из редактора кода с ошибкой

Ответ №1:

Вы можете сделать это с помощью перегрузок метода машинописи. Просто объявите все возможности аргументов и возвращайте значения следующим образом:

 function outer(a: number): (b: number) => any;
function outer(): (b?: number) => any;
function outer(a?: number) {
  return function inner(b?: number) {
    // some stuff
  };
}
 

и вы можете изменить значение any на то, что на самом деле вернет закрытие

VSCode правильно выдает ошибку во второй строке, потому что для этого требуется аргумент

код машинописного текста

Комментарии:

1. Оп просит function outer(a: number): (b?: number) => any; и function outer(): (b: number) => any; , противоположное тому, что у вас есть. Он должен ошибаться на первом, а не на втором.

2. Перегрузка функций работает в этом простом примере. Но я допустил ошибку, когда попытался применить этот подход к более сложному делу. Я обновил свой вопрос.