В простом JavaScript мы можем прочитать значение свойства объекта, используя переменную.

То есть это справедливо:

let obj = { a: 100, b: 'Need help with TypeScript', c: new Date() };
let prop = 'b';
console.log( obj[prop] );  // Need help with TypeScript

Однако приведенная ниже аннотация TypeScript, объявляющая prop как строку, приводит к указанной ошибке индекса.

let obj: object = { a: 100, b: 'Need help with TypeScript', c: new Date() };
let prop: string = 'b';
console.log( obj[prop] );  // TypeScript error element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.

Как я должен аннотировать вышеизложенное?

Изменить от 9 декабря 2019 г. Когда я размещал вопрос, я предполагал, что будет общий ответ, а не ответ, явно зависящий от моего примера объекта.

Мой вариант использования - это функция, которая принимает в качестве аргумента имя свойства. Функция сортирует массив по имени переданного свойства. Исходный код JavaScript, который я переношу в TS, будет сортировать любой массив объектов.

0
Karl 6 Дек 2019 в 23:10
Не аннотируйте obj вообще; пусть это выводится как тип {a: number, b: number, c: number}. Что касается prop, вам также не нужно аннотировать его, но вы должны либо заменить let на const, либо использовать let prop = "b" as const, например this.
 – 
jcalz
6 Дек 2019 в 23:15
- спасибо за ваш комментарий и пример. Я посмотрел на пример, и он работает, но я не понимаю, почему он работает. Почему объявление свойства как const имеет значение. У меня еще не было возможности попробовать ваше предложение для моего конкретного случая. Я буду, хотя. (Пожалуйста, посмотрите мои правки, сделанные сегодня.)
 – 
Karl
9 Дек 2019 в 18:04
«Почему объявление свойства как const имеет значение» Компилятор рассматривает const как сигнал о намерении, что значение не изменится (это верно только для примитивов, но что угодно), поэтому он делает вывод это как более узкий тип. Если вы пишете let prop = "b", он предполагает, что вы хотите, чтобы prop было string, потому что позже вы можете изменить его на какой-нибудь другой string. Если вы пишете const prop = "b", он знает, что prop всегда будет "b", поэтому он выводит тип строкового литерала "b". Я был бы рад превратить это в ответ, если он соответствует вашим потребностям.
 – 
jcalz
10 Дек 2019 в 17:39

1 ответ

Избегайте object как типа, TS не может вывести из этого, что делать.

Рассмотрите возможность добавления типа, который позволяет делать то, что вы хотите:

let obj: { [key: string]: number } = { a: 100, b: 200, c: 300 };
let prop: string = 'b';
console.log( obj[prop] );

Вы даже можете уточнить это, используя синтаксис [key in type], где type — это определение типа:

type props = 'a' | 'b' | 'c';
let obj: { [key in props]: number } = { a: 100, b: 200, c: 300 };
let prop: props = 'b';
console.log(obj[prop]);

Позже доступ к именованному свойству может быть упрощен с помощью интерфейса. Используя это как основу, оператор keyof очень полезен:

interface IProps{
  a: number,
  b: number,
  c: number
}
let obj: { [key in keyof IProps]: number} = { a: 100, b: 200, c: 300 };
let prop: keyof IProps = 'b';
console.log(obj[prop]);

Последнее больше предназначено для демонстрации, справки и демонстрации, а не совсем идеального ответа, который искал ОП.

0
Joerg Krause 6 Дек 2019 в 23:19