Как переписать машинопись для в цикле с активной проверкой "noImplicitAny"? - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть некоторые объявленные данные интерфейса:

export interface RegisterData {
    email: string
    password: string
    firstName?: string
    lastName?: string
}

И я хотел бы создать и объект, имеющий только непустые поля экземпляра интерфейса (и избегая некоторых непустых специальных полей, таких как пароль):

const nonEmptyData: any = { };

for(const itemId in registerData) {
  if(itemId !== "password" && registerData[itemId]) {
    nonEmptyData[itemId] = registerData[itemId];
  }
}

Однако, если активна проверка "noImplicitAny", я получаю следующую ошибку:

error TS7017: Element implicitly has an 'any' type because type 'RegisterData' has no index signature.

Как можно использовать 'in in' при активной проверке?

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Вы можете расширить интерфейс, добавив подпись индекса для повторения при необходимости:

interface IterableRegisterData extends RegisterData {
  [key: string]: string | undefined
}

const iterableRegisterData = registerData as IterableRegisterData;
for(const itemId in iterableRegisterData) {
  if(itemId !== "password" && iterableRegisterData[itemId]) {
    nonEmptyData[itemId] = iterableRegisterData[itemId];
  }
}

Если вам не нужно изменять registerData внутри цикла, вы можете добавить readonly к сигнатуре индекса, чтобы предотвратить добавление новых свойств в iterableRegisterData:

interface IterableRegisterData extends RegisterData {
  readonly [key: string]: string | undefined
}

Оригинальный ответ (плохая практика)

Просто добавьте подпись индекса:

export interface RegisterData {
    email: string
    password: string
    firstName?: string
    lastName?: string
    [key: string]: string | undefined
}

Обратите внимание, что вы должны использовать тип объединения, потому что некоторые из ваших свойств могут быть неопределенными. Если вы добавляете больше свойств с разными типами, вы должны добавить эти типы в подпись индекса:

export interface RegisterData {
    email: string
    age: number
    name?: string
    data: AdditionalData
    [key: string]: string | number | AdditionalData | undefined
}

Внимание

Как указано в комментариях, это может быть плохой практикой, поскольку добавление подписи индекса позволит вам добавить новые свойства, не определенные в интерфейсе, и, вероятно, вы не захотите этого:

const userData: RegisterData = { 
    email: 'user@domain.com,
    password: '1234'
}
userData['foo'] = 'baz'
0 голосов
/ 24 апреля 2018

Вы можете использовать Object.keys с утверждением, что массив ключей на самом деле является массивом ключей RegisterData:

for (const itemId of Object.keys(registerData) as Array<keyof RegisterData>) {
    if (itemId !== "password" && registerData[itemId]) {
        nonEmptyData[itemId] = registerData[itemId];
    }
}

Добавление подписи индекса также является вариантом, но не лучшим вариантом, что позволит индексировать по любой строке.

Редактировать

Или еще лучше, в зависимости от вашей цели и полифилов вы также можете использовать Object.entries

for (const [itemId, value] of Object.entries(registerData)) {
    if (itemId !== "password" && value) {
        nonEmptyData[itemId] = value;
    }
}
...