Как написать обобщенную функцию c в машинописи с параметрами значения или значения [] для двух параметров - PullRequest
1 голос
/ 06 марта 2020

Я пытаюсь создать обобщенную функцию c, которая будет принимать строковое значение hasMapName и другие ключи параметров в виде строки | string [] и обратный вызов, который вернет T | T [].

если ключ является строкой, обратный вызов должен вернуть T, а если ключом является String [], он должен вернуть обратно T [].

Попробовал следующий код:


    export function getData<K extends string | string[], T>(
      hashMapName: string,
      keys: K extends string[] ? string[] : string,
      serviceCallBack: K extends string[] ? () => Promise<T[]> : () => Promise<T>
    ): Promise<T> {
      return Array.isArray(keys)
        ? getDataForKeys<T>(hashMapName, keys, serviceCallBack)
        : getDataForKey<T>(hashMapName, keys, serviceCallBack);
    }

Но я получаю tserror для ключей в getDataForKey.

Ошибка:

Argument of type 'K extends string[] ? string[] : string' is not assignable to parameter of type 'string'.
  Type 'string | string[]' is not assignable to type 'string'.
    Type 'string[]' is not assignable to type 'string'.
      Type 'string | string[]' is not assignable to type 'string'.
        Type 'string[]' is not assignable to type 'string'.

Обновление 1:

Пожалуйста, найдите объявления для функций getDataForKeys и getDataForKey.


    declare function getDataForKey<T>(
      hashMapName: string,
      key: string,
      serviceCallBack: () => Promise<T>
    )

    declare function getDataForKeys<T>(
      hashMapName: string,
      key: string[],
      serviceCallBack: () => Promise<T[]>
    )

Поскольку мы строго следуем политике noExplicitAny, мы не сможем использовать любое ключевое слово для функциональных параметров.

Попробовав ответ @Dmitriy, вы столкнулись со следующей проблемой:

Argument of type '(() => Promise<T[]>) | (() => Promise<T>)' is not assignable to parameter of type '() => Promise<T[]>'.
  Type '() => Promise<T>' is not assignable to type '() => Promise<T[]>'.
    Type 'Promise<T>' is not assignable to type 'Promise<T[]>'.
      Type 'T' is not assignable to type 'T[]'

1 Ответ

0 голосов
/ 06 марта 2020

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

declare function getDataForKey<T>(...args: any[]): Promise<T>;
declare function getDataForKeys<T>(...args: any[]): Promise<T[]>;


export function getData<T>(
  hashMapName: string,
  keys: string,
  serviceCallBack: () => Promise<T>
): Promise<T>
export function getData<T>(
  hashMapName: string,
  keys: string[],
  serviceCallBack: () => Promise<T[]>
): Promise<T[]>
export function getData<T>(
  hashMapName: string,
  keys: string | string[],
  serviceCallBack: (() => Promise<T[]>) | (() => Promise<T>)
): Promise<T> | Promise<T[]> {
  return Array.isArray(keys)
    ? getDataForKeys<T>(hashMapName, keys, serviceCallBack)
    : getDataForKey<T>(hashMapName, keys, serviceCallBack);
}

getData("foo", "fooo", async () => "bar"); // works
getData("foo", ["fooo"], async () => ["bar"]); // works

getData("foo", ["fooo"], async () => "bar"); // error

// also works because T is not constrained to be non-array
getData("foo", "fooo", async () => ["bar"]); 

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...