Потеря информации о типе enum в цикле for - PullRequest
1 голос
/ 01 июля 2019

В приведенном ниже примере ключи myColors имеют тип Color.Однако у меня возникают проблемы с сохранением этой информации при зацикливании объекта myColor.

enum Color {
  Red = 'RED',
  Green = 'GREEN',
}

type MyColors = {
  [C in Color]?: string;
}

const myColors: MyColors = {
  [Color.Red]: '#8B0000',
}

for (const [name, hex] of Object.entries(myColors)) {
  // name is of type string here instead of Color
}

Используя обычный цикл for in, или Object.keys(myColors) также преобразует ключ enum в строку.

Есть ли способ сохранить тип ключей при циклическом переключениисвойства объекта?Если нет, то как я могу утверждать, что name в моем цикле имеет тип Color?

1 Ответ

3 голосов
/ 01 июля 2019

Определение TypeScript для Object.entries перегружено, но обе перегрузки явно используют строку в качестве типа ключа. От lib/lib.es2017.object.d.ts:

/**
 * Returns an array of key/values of the enumerable properties of an object
 * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
 */
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];

/**
 * Returns an array of key/values of the enumerable properties of an object
 * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
 */
entries(o: {}): [string, any][];

Я уверен, что для этого есть веская причина. :-) Но вы можете определить свой собственный entries, который не использует string:

// Our `entries` function
function entries<T>(o: T): [keyof T, T[keyof T]][] {
    return Object.entries(o) as unknown as [keyof T, T[keyof T]][];
}

Тогда это работает:

for (const [name, hex] of entries(myColors)) {
  // type of `name` is `Color` now
}

Если продолжить, я обнаружил, что если добавить следующее объявление:

interface ObjectConstructor {
    /**
     * Returns an array of key/values of the enumerable properties of an object
     * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
     */
    entries<T>(o: T): [keyof T, T[keyof T]][];
}

При этом ваш оригинальный код работает так, как вы ожидали:

for (const [name, hex] of Object.entries(myColors)) {
  // type of `name` is `Color` now
}

(Я дважды проверил это с реальным компилятором, а не только с игровой площадкой, имея const n: Color = name; в теле цикла. TypeScript жалуется на это без объявления, но с объявлением, что он счастлив.)

Но , некоторые проблемы в списке проблем TypeScript заставляют меня думать, что определение может вызвать проблемы с другими вещами, которые вы передаете Object.entries, в частности этот и этот комментарий . Таким образом, вы можете захотеть иметь отдельную функцию (которая, скорее всего, уберет JIT) и использовать ее там, где это необходимо.

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