如何创建一个对象,其中的值是通过函数运行键的结果?

问题描述 投票:0回答:1

我想创建一个对象,其中键以文字类型定义,而值是通过函数运行每个键的结果。这个想法是拥有一个由文字类型中的条目定义的对象。我还希望能够为特定键添加不同的值,这些键不应该通过其余键运行的函数来运行。

这是我正在尝试做的一个示例:

function capitalizeString(string: string) {
  return string[0].toUpperCase() + string.substring(1)
}

type fruits = "apple" | "orange" | "pineapple" | "pear" | "orange" | "melon"

const fruitObject:{ [key in fruits]: string} = {
  // Would create key/value pairs of all of the entries in the literal type
  [key]: capitalizeString(key),
  // custom values that aren't being handled by the function
  orange: "oRaNgE",
  melon: "meloN",
}

这是一个简单的示例,我知道有更好的方法来解决这个特定问题,但我更感兴趣的是是否可以做到这一点,而不是如何改进这个特定的示例。

typescript
1个回答
0
投票

在你的

fruitObject
定义中,你试图执行某种理解,这在 TypeScript 中是不可能的。不过,您的问题仍然有解决方案。

首先,我们不能循环联合类型,因为它们存在于类型域中。相反,我们可以创建一个包含键的

readonly
列表并提取其类型。这样我们就可以有效地循环联合类型。

const fruits = ["apple", "orange", "pineapple", "pear", "orange", "melon"] as const;
type Fruits = (typeof fruits)[number];
type FruitObject = {[Key in Fruits]: string}

Fruits
现在将是
"apple"
"orange"
"pineapple"
等的联合类型,与原始
fruits
类型相同。通过这种方法,我们可以编辑数组以包含更多水果,所有内容都会相应更新。

接下来,我们需要创建一个函数来接受水果列表并将该数组简化为一个对象:

function fruitObjectFactory(fruitArray: readonly Fruits[]): FruitObject {
  return fruitArray.reduce((acc, key) => {
    acc[key] = capitalizeString(key);
    return acc;
  }, {} as FruitObject);
}

这可以使用数组

.reduce()
方法来完成,其中累加器的类型为
FruitObject

最后,我们可以在对象定义中调用此函数,并使用展开运算符 (

...
),我们可以组合两个对象。

const fruitObject: FruitObject = {
  ...fruitObjectFactory(fruits),
  orange: "oRaNgE",
  melon: "meloN",
}

您会注意到

...fruitObjectFactory(fruits)
将创建一个对象,其中包含
fruits
数组中的所有字符串,但您想要例外。
orange: "oRaNgE"
melon: "meloN"
的定义分别覆盖
orange: "Orange"
melon: "Melon"
键值对。

注意,

readonly
回调方法中的
.reduce()
不是必需的。我添加它只是为了传递原始
fruits
数组,由于
readonly
运算符,该数组的类型为
as const

© www.soinside.com 2019 - 2024. All rights reserved.