Возвращаемый тип объекта с такими же параметрами - PullRequest
0 голосов
/ 28 апреля 2020

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

class CountryFilterFormatterService {
  public groupCountriesByRegion(
    groupLabelKey: string,
    groupValuesKey: string,
  ): {[groupLabelKey]: string, [groupValuesKey]: string}[] {
      return [
          {
              [groupLabelKey]: 'foo',
              [groupValuesKey]: 'bar'

        }
    ]
  }
}

export default CountryFilterFormatterService;


Я бы хотел, чтобы у функции groupCountriesByRegion был тип возврата {[groupLabelKey as string]: string, [groupValuesKey]: Country[]}[], но я получаю следующую ошибку: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type

Как я могу достичь такого типа возврата?

детская площадка

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Я бы предложил сделать функцию generi c как типа groupLabelKey, так и типа groupValuesKey, например:

class CountryFilterFormatterService {
    public groupCountriesByRegion<LK extends string, VK extends string>(
        groupLabelKey: LK,
        groupValuesKey: VK,
    ): { [K in LK | VK]: string }[] {
        return [
            {
                [groupLabelKey]: 'foo',
                [groupValuesKey]: 'bar'
            } as { [K in LK | VK]: string }
        ]
    }
}

Там это два универсальных параметра типа c: LK и VK, соответствующие (надеюсь) строковым литералам типов значений, переданных для groupLabelKey и groupValuesKey соответственно. Тип возвращаемого значения - это массив сопоставленного типа , {[K in LK | VK]: string}. Это означает «объект, ключи которого LK и VK, а значения которого в этих ключах string s».

Здесь есть морщина в том, что значение { [groupLabelKey]: 'foo', [groupValuesKey]: 'bar' } не распознается компилятор как имеющий правильный тип. Он видит обобщенный c вычисленный ключ и расширяет его до string, и, следовательно, тип этого объекта определяется как { [k: string]: string }, и компилятор будет жаловаться, если вы вернете его как есть. Существует открытая проблема GitHub по этому поводу, microsoft / TypeScript # 13948 , но пока что так оно и есть.

Обходной путь - использовать утверждение типа в качестве Я сделал выше, и добавляю as { [K in LK | VK]: string } после литерала объекта. Есть и другие обходные пути, но этот не касается кода времени выполнения.

Итак, давайте посмотрим, работает ли он:

const x = (new CountryFilterFormatterService()).groupCountriesByRegion("baz", "qux");
// const x: { baz: string; qux: string; }[]

x.forEach(
    v => console.log(v.baz.toUpperCase() + " " + v.qux.toUpperCase())
); // FOO BAR

Хорошо выглядит. Я передал "baz" и "qux", и компилятор видит тип x как Array<{baz: string, qux: string}>, как вы, вероятно, хотите.


Хорошо, надеюсь, это поможет; удачи!

Детская площадка ссылка на код

0 голосов
/ 28 апреля 2020

Как насчет этого? Поскольку вы предоставляете динамические ключи c, вы можете указать их только один раз. Если у вас есть фиксированный набор ключей, вы также можете создать Enum и использовать его вместо этого в generi c string

class CountryFilterFormatterService {
  public groupCountriesByRegion(
    groupLabelKey: string,
    groupValuesKey: string,
  ): {[groupLabelKey: string]: string}[] {
      return [
          {
              [groupLabelKey]: 'foo',
              [groupValuesKey]: 'bar'
            
        }
    ]
  }
}

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