Элемент неявно имеет тип ‘any’, потому что выражение типа ‘string’ не может использоваться для индексации типа ‘Type’

#sql-server #typescript #object #types #index-signature

#sql-server #typescript #объект #типы #индекс-подпись

Вопрос:

Я пытаюсь обрезать значения из массива объектов, который возвращается из REST API.

Это interface для объекта, который я ожидаю.

 interface IProduct {
  productId: number;
  qty: number;
  code: string;
  customer: string;
  description: string;
}
 

Я пытаюсь перебрать массив объектов и обрезать все значения объекта.

 products.forEach(record => {
  if (record) {
    Object.keys(record).map(key => {
      record[key] = record[key].trim();
    });
  }
});
 

Я получаю следующую ошибку.

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

Я пытался добавить подпись индекса к объекту, но безуспешно. [key: string]: string а также key: {[index: string]: string} .

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

Вот ссылка на объект.

 const products: Product[] = [
  {
    productId: 1,
    qty: 100,
    code: 'code',
    customer: 'customer',
    description: 'the description',
  },
  {
    productId: 2,
    qty: 102,
    code: 'code',
    customer: 'customer',
    description: 'the description',
  },
];
 

Большое спасибо

Ответ №1:

Определение для Object.keys :

 interface ObjectConstructor {
  keys(o: object): string[];
  keys(o: {}): string[];
}
 

Это потому, что вы можете написать такой код:

 const object = {
  productId: 1,
  qty: 100,
  code: 'code',
  customer: 'customer',
  description: 'the description',
  someOtherKey: 'foo', // extra key here
};
const product: IProduct = object;
const keys = Object.keys(product); // keys contains someOtherKey
 

Чтобы исправить вашу ошибку, вы могли бы использовать утверждение типа:

 products.forEach(record => {
  if (record) {
    (Object.keys(record) as (keyof IProduct)[]).map(/* ... */);
  }
});
 

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

 declare global {
  interface ObjectConstructor {
    keys<K extends PropertyKey>(o: Record<K, unknown>): K[];
  }
}
// declare global can only be in a module, so if the file isn't
// a module already you'll need to add this
export {};
 

Таким образом, вам не понадобится утверждение типа, но технически это небезопасно.