Расширение аргумента типа функции по индексу - PullRequest
2 голосов
/ 21 февраля 2020

Итак, эта хитрая функция принимает функцию fn и число n и возвращает функцию-обертку, которая вызывает fn с измененным n -ым аргументом. n-й аргумент fn является объектом, свойство plugins которого является массивом PluginObject объектов, тогда как n-й аргумент возвращаемой функции должен иметь немного другой тип: ее свойство plugins Array<string | PluginObject>, также он может иметь необязательное свойство pluginSearchDirs: string[], остальные свойства взяты из типа n -ого аргумента исходной функции fn.

Вопрос в том, как на Земле я могу преобразовать это в TypeScript?

function withPlugins(fn, n) {
    return (...args) => {
        const opts = args[n];
        args[n] = {
            ...opts,
            plugins: loadPlugins(opts.plugins, opts.pluginSearchDirs)
        };
        return fn(...args);
    };
}

Вот что я пробовал, но это не сработало (withPlugins(myFn, 0) имеет тот же тип, что и myFn, детская площадка ) :

interface PluginObject {
  foo: any;
}

declare function loadPlugins(
  plugins?: (PluginObject | string)[],
  pluginSearchDirs?: string[]
): PluginObject[];

function withPlugins<
  Args extends any[],
  Result,
  OptsIdx extends number
>(
  fn: (...args: Args) => Result,
  optsArgIdx: OptsIdx
): (
  ...args: {
    [P in keyof Args]: OptsIdx extends P
      ? Args[P] & {
          plugins: (PluginObject | string)[];
          pluginSearchDirs?: string[];
        }
      : Args[P];
  }
) => Result {
  return (...args) => {
    const opts = args[optsArgIdx];
    args[optsArgIdx] = {
      ...opts,
      plugins: loadPlugins(opts.plugins, opts.pluginSearchDirs)
    };
    return fn(...args as any);
  };
}
...