Деструктурирование смешанного массива let/const из разделенной строки

#javascript #arrays #typescript #ecmascript-6

Вопрос:

TS выдает ошибку:

 'parsedHours' is never reassigned. Use 'const' instead    prefer-const
'parsedMinutes' is never reassigned. Use 'const' instead  prefer-const
 

При попытке деконструировать этот массив после разделения строки:

 let [
  parsedHours = '00',
  parsedMinutes = '00',
  parsedSeconds = '00',
  parsedMillis = '000'
] = "12:34:56".split(':');

if (parsedSeconds.includes('.')) {
  [parsedSeconds, parsedMillis] = parsedSeconds.split('.');
}
 

Часы и минуты должны быть объявлены как константы, но секунды и миллисекунды могут изменяться, поэтому их следует объявлять как let.
Это можно исправить во многих подходах, но я не могу найти красивый способ сделать это.

Есть какие-нибудь идеи?

Комментарии:

1. // @ts-ignore ИМО

2. «TS выдает ошибку» Я на 99% машинописный текст-это не то, на что здесь жалуются. TSLint или ESLint, но не машинописный текст.

Ответ №1:

Вы можете использовать String.split() регулярное выражение для разделения на [.:] :

 const splitTime = (str) => {
  const [
    parsedHours = '00',
    parsedMinutes = '00',
    parsedSeconds = '00',
    parsedMillis = '000'
  ] = str.split(/[.:]/);

  console.log({
    parsedHours,
    parsedMinutes,
    parsedSeconds,
    parsedMillis
  });
}

splitTime("12:34:56")

splitTime("12:34:56.35") 

Комментарии:

1. Именно об этом я и думал, когда выгуливал собаку. Thx 🙂

Ответ №2:

Если единственная причина, по которой Секунды и Миллис могут измениться, заключается в этом единственном if блоке, то ваш подход в первую очередь ошибочен. Это связано с тем , что на начальном split parsedSeconds этапе на самом деле не «проанализированные секунды», а «проанализированные секунды с необязательной десятичной частью».

Вместо этого рассмотрите возможность анализа вашего фактического формата, в данном случае с помощью регулярного выражения:

 const [
  , // ignore "full match"
  parsedHours,
  parsedMinutes,
  parsedSeconds,
  parsedMillis = "000"
] = "12:34:56".match(/^(d{2}):(d{2}):(d{2})(?:.(d{3}))?$/) || [];
 

В этом сценарии все проанализированные фрагменты действительно постоянны.

Обратите внимание на этот финал || [] , который улавливает случай, когда ввод не соответствует ожидаемому формату. Вы могли бы назвать полное совпадение parsedResult и проверить if( !parsedResult) throw 'something';

Комментарии:

1. Да, я также вернулся и бросил в него регулярное выражение.

2. @Ти Джей Краудер Классическая проблема XY, верно? 😀 «Как мне смешать let и const ?» «Почему ты этого хочешь?»

Ответ №3:

В принципе, у вас есть несколько вариантов:

  1. Отключите правило lint (я на 99% уверен, что это говорит не сам текст, а TSLint, ESLint или что-то подобное).
  2. Сохраните массив, затем используйте const или let по желанию.
  3. Используйте const для всех них регулярное выражение (возможно, с именованными группами захвата), которое обрабатывает возможные форматы, которые вы ему передаете.

Вот #2:

 const result = "12:34:56".split(":");
const [parsedHours = "00", parsedMinutes = "00"] = resu<
let [, , parsedSeconds = "00", parsedMillis = "000"] = resu<
// ...
 

Вот #3:

 const rexTime = /^(?<hours>d{1,2}):(?<minutes>d{1,2}):(?<seconds>d{1,2})(?:.(?<millis>d{1,3}))?$/;
function example(timeString) {
    const {
        groups: {
            hours = "00",
            minutes = "00",
            seconds = "00",
            millis = "000"
        } = {}
    } = rexTime.exec(timeString) ?? {};
    console.log(
        timeString,
        "=>",
        hours,
        minutes,
        seconds,
        millis
    );
}

example("12:34:56");
example("12:34:56.123"); 

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

Ответ №4:

Почему бы не заменить . это на то : и не разбить все на части? (если вы не хотите этого делать, второй образец исключает . заменить)

Кстати, вы можете просто распределить остальное как const, а затем позволить дополнительным:

 const [
  parsedHours = '00',
  parsedMinutes = '00',
  ...rest
] = "12:34:56.123".replace('.', ':').split(':');
let [
  parsedSeconds = '00',
  parsedMillis = '000'
] = rest;  

   console.log(rest);

const [
  parsedHours2 = '00',
  parsedMinutes2 = '00',
  ...rest2
] = "12:34:56.123".split(':');
let [
  parsedSeconds2 = '00',
  parsedMillis2 = '000'
] = rest2;  

console.log(rest2);