Как использовать значения перечисления для индексации объекта? - PullRequest
0 голосов
/ 18 июня 2020

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

enum Foods {
  bread = "bread",
  meat = "meat",
}

type ShoppingList = {
  [Foods.bread]: string;
  [Foods.meat]: string;
};

const shoppingList: ShoppingList = {
  bread: "1 loaf",
  meat: "2 lbs",
};

Object.keys(Foods).forEach((item) => {
  console.log(shoppingList[item]);
});

Этот делает сборку с tsc, но ts-node и VS Code оба сообщают:

error TS7053: Element implicitly has an 'any' type because expression of type
  'string'  can't be used to index type 'ShoppingList'. No index signature with
  a parameter of type 'string' was found on type 'ShoppingList'.

17   console.log(shoppingList[item]);
                 ~~~~~~~~~~~~~~~~~~

Понятно, потому что Object.keys возвращает string[]. Однако мы с вами знаем, что эти строки будут только членами Foods. И поскольку ShoppingList только использует Foods в качестве ключей, мы должны иметь возможность использовать любой член Object.keys для индексации shoppingList.

Это имеет смысл концептуально, но как Могу ли я сообщить об этом TypeScript?

Edit : Foods и ShoppingList должны придерживаться этих двух значений, т.е. здесь нет ключей Dynami c.

1 Ответ

1 голос
/ 18 июня 2020

Вы не можете использовать только enum.

Конечно, вы можете просто использовать приведение, чтобы сообщить TS, какой будет тип item:

console.log(shoppingList[item as Foods]);

Но что было бы утомительно писать каждый раз, когда вам нужно преобразовать Foods.

Другой вариант - объявить массив, который явно определен:

enum Foods {
  bread = "bread",
  meat = "meat",
}

const FoodsArray = [Foods.bread, Foods.meat];

// Optional: use [key in Foods] to consolidate type definition
type ShoppingList = {
  [key in Foods]: string;
};

const shoppingList: ShoppingList = {
  bread: "1 loaf",
  meat: "2 lbs",
};

FoodsArray.forEach((item) => {
  console.log(shoppingList[item]);
});

Это немного избыточно для нужно вручную объявлять и обновлять массив? Да. Но, насколько я знаю, нет никакого способа, чтобы вывести точные типы непосредственно из enum.

1016 *https://www.typescriptlang.org/play/index.html?ssl=17&ssc=4&pln=1&pc=1#code / KYOwrgtgBAYg9nAJgZygbwFBSgIwE7ACGiUAvFAET5GIUA0WUERALmZc4S-RgL4YYAxnBDI28JMgCCePIQCe7ANoSUAOmrE6sBOs4sAugG4BLeQAdgUAMoALOOfMBLEAHMAMk7HtM2JQGtgRRcdSQMALigxPBdXE14TIRFvZHtHWM8xSLsHZzdMtnJfXAJiSIoARigAGzhCADMebH1ygCYanGQeBIFVaVkFNXq4PABRQkFbAAoppxZgCABKMgA + dEZhUThq4DVa1ynU3IyvFiU5hYNF + OugA
...