具有相同参数的返回类型对象

时间:2020-04-28 09:18:43

标签: typescript

我希望能够返回一个对象数组,其键名将取决于函数接收的参数。我有以下内容:

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

如何实现这种返回类型?

playground

2 个答案:

答案 0 :(得分:0)

这个怎么样?由于要提供动态键,因此只能指定一次。如果您有一组固定的键,则还可以创建一个Enum并将其用于通用string

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

export default CountryFilterFormatterService;

答案 1 :(得分:0)

我的建议是使函数generic的类型为groupLabelKeygroupValuesKey,如下所示:

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 }
        ]
    }
}

有两个通用类型参数:LKVK,对应于groupLabelKeygroupValuesKey传递的值的(希望)string literal types分别。返回类型是mapped type{[K in LK | VK]: string}的数组。这意味着“对象的键为LKVK,并且这些键处的值为string s。

这里有一个折衷之处,就是编译器无法将值{ [groupLabelKey]: 'foo', [groupValuesKey]: 'bar' }识别为正确的类型。它看到通用的计算密钥并将其扩展到string,因此该对象的类型被推断为{ [k: string]: string },如果您按原样返回它,编译器将抱怨。与此相关的还有一个公开的GitHub问题,microsoft/TypeScript#13948,但现在是这样。

解决方法是使用type assertion,就像我在上面所做的那样,然后在对象文字后添加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}>,这可能是您想要的。


好的,希望能有所帮助;祝你好运!

Playground link to code