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


95

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

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

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


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]));
Робби Корнелиссен


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. Это решило мою проблему и работает хорошо или я. Надеюсь, это поможет и вам.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.