Как использовать Object.values ​​с машинописью?

135

Я пытаюсь сформировать строку, разделенную запятыми, из объекта,

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const values = Object.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

Как это сделать с помощью TypeScript?

получить файл ошибки:

severity: 'Error'
message: 'Property 'values' does not exist on type 'ObjectConstructor'.'
at: '216,27'
source: 'ts'
user2280016
источник

Ответы:

106

вместо этого используйте Object.keys.

const data = {
  a: "first",
  b: "second",
};

const values = Object.keys(data).map(key => data[key]);

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);
Холи-ява
источник
90
Обратите внимание, что это альтернатива (хорошая!), А не реальный ответ о том, как использовать ES7 Object.valuesв TS для решения ошибки компиляции OP. Для этого вам просто нужно ES2017в --libнастройках.
Аарон
4
@ Аарон ваше решение настолько сложное, что любой новичок в машинописи не может его принять, для компиляции вы должны добавить ES2017библиотеку lib и включить библиотеку polyfills, где ее используете.
Холи-
9
@ holi-jave Это не «мое решение», просто то, как работают TS и нестандартные функции JS, как попытка использования OP ES7/Object.values(). Может быть, вы думаете, что это сложно (я не согласен), но это просто природа попыток использовать будущие функции, как Object.values()сегодня. Это всегда было так. Даже Object.keys()если вы нацелены на ES3 или хотите поддерживать IE8 (надеюсь, вы больше этого не сделаете!), В общем, неплохо понимать функции ES, поддержку браузера и полифиллинг, если вы занимаетесь веб-разработкой!
Аарон
@ Аарон Я не сказал, что это сложно, но для кого-то новичка в машинописи / javascript более сложен и не принят.
Холи-
224

Object.values()является частью ES2017 , и вы получаете ошибку компиляции, потому что вам нужно настроить TS для использования библиотеки ES2017. Возможно, вы используете библиотеку ES6 или ES5 в текущей конфигурации TS.

Решение: используйте es2017или es2017.objectв вашем --libварианте компилятора .

Например, используя tsconfig.json:

"compilerOptions": {
    "lib": ["es2017", "dom"]
}

Обратите внимание , что таргетинг ES2017 с машинописью никак не испускает polyfills в браузере для ES2017 (имея в виде выше решает вашу компиляции ошибки, но вы можете столкнуться во время выполнения ошибки , потому что браузер не реализует ES2017 Object.values), это до вас , чтобы polyfill вашего проекта закодируйте себя, если хотите. А так как Object.valuesеще не очень хорошо поддерживается всеми браузерами (на момент написания этой статьи) , вы определенно хотите polyfill: core-jsбудет делать эту работу .

Аарон Белл
источник
1
@ErikvanVelzen Вы отредактировали ответ, чтобы изменить регистр ES2017на, es2017но AFAIK это не обязательно, но я всегда хочу узнать, была ли причина для изменения?
Аарон Белл
2
^ Чтобы ответить на мой собственный вопрос: ES2017, DOM( в верхнем регистре) приведено в tsc --initкомментариях , как допустимые значения и корректно работает в компиляторе, но схема JSON перечисляет только es2017, domварианты ( в нижнем регистре), так что JSON IDE / ЛИНТЕР флаг ES2017, DOMа недопустимые значения (даже если они действительны). Немного смущает.
Аарон Белл
Действительно, это была причина. Он работает в верхнем регистре, как вы заметили. tsc --helpхотя отображает строчные буквы
Эрик ван Велзен
Разве core-js не включен в angular, если нет, то как добавить этот pollyfill?
Самиулла Хан
1
@ Totty.js Библиотечные файлы, включенные в TS, предназначены только для проверки типов , другими словами, на самом деле они не генерируют какие-либо полизаполнения библиотеки JS для таких вещей, как Object.values(). Другими словами, вы можете обойти ошибку компиляции, но все равно столкнетесь с ошибками во время выполнения, если вы запускаете в браузере, который не имеет Object.values().
Аарон Белл
18

Вы можете использовать это Object.valuesв TypeScript, (<any>Object).values(data)если по какой-то причине вы не можете обновить ES7 в tsconfig.

mtpultz
источник
4
@Aaron во время публикации были комментарии, указывающие, что у людей, использующих определенную версию Angular, были проблемы с обновлением библиотеки там, где она не работала. Вот почему я положилif for some reason you can't update to ES7 in tsconfig
mtpultz
11

Вместо того

Object.values(myObject);

использование

Object["values"](myObject);

В вашем примере:

const values = Object["values"](data).map(x => x.substr(0, x.length - 4));

Это скроет ошибку компилятора ts.

Киан
источник
1
ты гений (^ - ') b
harufumi.abe
Элемент неявно имеет тип 'any', потому что тип 'ObjectConstructor' не имеет индекса signature.ts (7017)
Tyguy7
6
Это неправильное использование TS. Вы должны сконфигурировать компилятор с libнастройкой, чтобы отразить, как вы его используете, а не намеренно избегать компилятора.
Аарон
1
@AaronBeall это хорошее применение, если по какой-то причине вы не можете перейти на es2017
Dino
@Dino Вам не нужно обновляться до es2017, вы можете использовать core-js для полного заполнения вплоть до ES5. У TypeScript нет времени выполнения, libнастройка только для правильной проверки типов.
Аарон
11

Я увеличил цель, tsconfig.jsonчтобы включить эту функцию в TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}
Лукас Игнатавичюс
источник
Изменение цели не является решением, если вы хотите сохранить совместимость со старыми браузерами. Typescript должен уметь передавать синтаксис ES2017 в ES2015.
Случайный
4

Я только что решил эту проблему с Angular 6, используя CLI и рабочие пространства для создания библиотеки с использованием ng g library foo.

В моем случае проблема была в tsconfig.lib.jsonпапке библиотеки, которая не была es2017включена в libраздел.

Любой, кто сталкивается с этой проблемой в Angular 6, просто должен убедиться, что вы обновляете tsconfig.lib.jsonкак ваше приложение, так и ваше приложение.tsconfig.json

Нил Стивенс
источник
я поместил es2017 как в tsconfig.lib, так и в tsconfig.json, но все же я получаю сообщение об ошибке «записи не существует в объекте» при попытке использовать записи. Что-нибудь еще, что я должен изменить / обновить?
Морис
я изменил цель в tsconfig.lib на es2017 только сейчас, все та же ошибка.
Морис
2

Наличие моей tslintконфигурации правил здесь всегда заменяет строку Object["values"](myObject)на Object.values(myObject).

Два варианта, если у вас есть такая же проблема:

(Object as any).values(myObject)

или

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`
kuncevic.dev
источник
1
Почему вы когда-нибудь захотите использовать Object["values"]?
Аарон
-4

Самый простой способ - привести к Objectтому any, вот так:

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const obj = <any>Object;
const values = obj.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

И вуаля - без ошибок компиляции;)

Максимилиан Мажер
источник