Использование синтаксиса распространения и new Set () с машинописным текстом

95

Я использую следующий код для получения уникальных номеров:

let uniques = [ ...new Set([1, 2, 3, 1, 1]) ]; // [1, 2, 3]

Однако машинописный текст сообщает об ошибке: Тип «Set» не является типом массива. Я не машинописный ниндзя, может кто-нибудь сказать мне, что здесь не так?

Eggy
источник
4
Я думаю, что это просто ошибка Typescript, если используемая вами версия утверждает, что поддерживает ES2015.
Pointy
1
@Pointy Извините, я должен включить версию tsc 1.6.2
Eggy

Ответы:

46

Это недостающая функция. На данный момент TypeScript поддерживает итерации только в массивах.

басарат
источник
Спасибо за разъяснение. Я буду использовать .filter () или что-то еще, чтобы выполнить свою работу. Я также нашел несколько проблем с этой конкретной ошибкой на github. Я буду следить за этим в будущих выпусках.
Eggy
104

Обновление : с помощью Typescript 2.3 теперь вы можете добавить "downlevelIteration": trueв свой tsconfig, и это будет работать при ориентации на ES5.

Недостатком downlevelIterationявляется то , что TS придется вводить совсем немного шаблонный , когда transpiling. Единственная строка из вопроса транслируется с 21 строкой добавленного шаблона: (с Typecript 2.6.1)

Этот шаблон будет внедрен один раз в файл, который использует итерацию нижнего уровня, и этот шаблон можно уменьшить, используя "importHelpers"параметр через tsconfig. (См. Это сообщение в блоге об итерации нижнего уровня и importHelpers)

В качестве альтернативы, если поддержка ES5 для вас не имеет значения, вы всегда можете просто настроить таргетинг на «es6», и в этом случае исходный код будет работать без флага «downlevelIteration».


Оригинальный ответ:

Это похоже на причуду машинописной транспиляции ES6. ...Оператор должен работать на все , что имеет свойство итератора, (к которым обращается obj[Symbol.iterator]) и наборы имеют это свойство.

Чтобы обойти эту проблему , вы можете использовать , Array.fromчтобы преобразовать набор в массив первым: ...Array.from(new Set([1, 2, 3, 1, 1])).

Рецам
источник
@Restam: Предоставляет ли машинописный текст полифилы для Array.from в IE, если "target": "es5" в tsconfig.json?
jackOfAll
1
@jackOfAll Нет, Typescript не выполняет за вас полифиллинг прототипов. Если вы установите "target": "es5", это должно выдать вам ошибку компилятора, если вы попытаетесь использовать метод, который необходимо полифиллировать.
Retsam
1
@Restam отличное решение с Array.from. Большинство людей просто отказываются от этого. спасибо за реальное решение!
rayepps
Это не ошибка, они просто не поддерживают его для es5цели (см. Github.com/Microsoft/TypeScript/issues/4031 ). Array.fromдолжен работать, если в вашем списке в tsconfig есть es2015или выше ( es2017, esnext) lib.
Саймон Хениш
1
@ SimonHänisch Спасибо за ссылку: я обновил свой ответ, я больше не называю это «ошибкой», а «причудой транспиляции», что, вероятно, является более точным термином. Я также добавил информацию о варианте итерации нижнего уровня из этой ссылки, которая также решает исходную проблему.
Retsam
74

Вы также можете использовать метод Array.from для преобразования Set в Array

let uniques = Array.from(new Set([1, 2, 3, 1, 1])) ;
console.log(uniques);

Нейт Гетч
источник
Какой смысл распространять массив только для того, чтобы вернуть его в новый массив?
Робби Корнелиссен,
1
Если невозможно настроить таргетинг на "es6", в tsconfig. И использование Set с оператором распространения требуется, как бы вы это сделали?
Нейт Гетч,
Дело в том, что если вы используете Array.from(), вам больше не нужен оператор спреда. Это просто увеличивает накладные расходы. let uniques = Array.from(new Set([1, 2, 3, 1, 1]));
Робби Корнелиссен
9

Вам нужно установить "target": "es6",в вашем tsconfig.

phil294
источник
1

В Javascript:

[ ...new Set([1, 2, 3, 1, 1]) ]

В машинописном тексте:

Array.from(new Set([1, 2, 3, 1, 1]))

В состоянии реакции (setState):

setCart(Array.from(new Set([...cart, {title: 'Sample', price: 20}])));
Наджати
источник
0

Чтобы заставить его работать, вам нужно либо «target»: «ES6» (или выше), либо «downlevelIteration»: true в compilerOptions вашего tsconfig.json. Это решило мою проблему и работает хорошо или я. Надеюсь, это поможет и вам.

Маюр Санер
источник