Как вы деструктурируете именованные группы захвата?

В JavaScript использование именованных групп захвата довольно удобно.:

const auth = 'Bearer AUTHORIZATION_TOKEN'
const { groups: { token } } = /Bearer (?<token>[^ $]*)/.exec(auth)
console.log(token) // "AUTHORIZATION_TOKEN"

Когда я пробую это в машинописном тексте, он не компилируется, потому что groups может быть null. Если я поставлю ! после exec(...), это просто ударит по банке: token может быть неопределенным.

В typescript есть ли способ деструктурировать регулярное выражение, как указано выше?

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
3
0
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

ОБНОВИТЬ: ответ Берги — более правильный и безопасный способ добиться этого.


Это некрасиво, но что-то вроде этого будет работать:

const auth = 'Bearer AUTHORIZATION_TOKEN'
type RegexTokenObj = { groups: { token: string } };
const { groups: { token } } = (/Bearer (?<token>[^ $]*)/.exec(auth) as unknown as RegexTokenObj)
console.log(token) // "AUTHORIZATION_TOKEN"

Если вы просто попробуете const { groups: { token } } = (/Bearer (?<token>[^ $]*)/.exec(auth) as RegexTokenObj), он будет кричать вам, что "Conversion of type 'RegExpExecArray | null' to type 'RegexTokenObj' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.». Таким образом, мы можем преобразовать в unknown перед приведением к типу, который мы знаем/ожидаем, что он будет. Тем не менее, мы переопределяем систему типов здесь, поэтому мы должны быть уверены, что мы уверены, что мы правы в этом, так что будьте осторожны.

Забавный. Я никогда раньше не использовал type в функции. Если бы я хотел быть более типизированным, как бы выглядел этот код?

Daniel Kaplan 23.04.2022 03:07

Я использовал type больше как визуальный помощник — вы могли определить его снаружи или просто убрать абстракцию и заменить тип прямо в строке, присваивающей token. Что касается того, как сделать это более безопасным для типов... Честно говоря, я не уверен - возможно, у другого пользователя может быть лучший и более безопасный подход, чем этот, которым они могут поделиться в качестве ответа...

Alexander Nied 23.04.2022 03:17
ответ Берги более правильный; typesafe способ сделать это.
Alexander Nied 23.04.2022 20:40

Вы также можете использовать прямое присвоение переменной token:

const auth = 'Bearer AUTHORIZATION_TOKEN'
const token = /Bearer (?<token>\S+)/.exec(auth)?.groups?.token
console.log(token); // => "AUTHORIZATION_TOKEN"

Поскольку вы знаете название группы, вы можете обратиться к значению совпадения group?.token.

Кроме того, примечание (?<token>\S+) захватывает один или несколько символов без пробелов.

Ответ принят как подходящий

It doesn't compile because groups could be null.

Нет, он не компилируется, потому что .exec() может вернуть null, если регулярное выражение не совпадает. Попытка получить доступ к такому свойству, как .groups, вызовет ошибку TypeError: невозможно прочитать свойства null.

В этом случае вам понадобится резервное значение (с использованием нулевое слияние и инициализаторов по умолчанию) для деструктуризации:

const { groups: {token} = {} } = /Bearer (?<token>[^ $]*)/.exec(auth) ?? {}

или проще с необязательная цепочка:

const { token } = /Bearer (?<token>[^ $]*)/.exec(auth)?.groups ?? {}

Спасибо! Я немного смущен, как это работает в целом. /Bearer (?<token>[^ $]*)/.exec(auth)?.groups Я думаю, что это говорит «вернуть groups, если он существует, иначе вернуть undefined». ?? {} говорит: «Если результат нулевой, верните пустой объект». Но с левой стороны вы разбираете этот (потенциально) пустой объект на { token }, и когда я навожу курсор на token на игровой площадке ts, он говорит, что это тип string. Откуда компилятор знает об этом и почему это не ошибка «token не существует для типа {}»?

Daniel Kaplan 24.04.2022 00:02

Компилятор знает, что groups — это Record<string, string> (или {[group: string]: string}). .token может существовать, а может и не существовать (компилятор не знает группы регулярных выражений), но если он существует, то это string. И {} предполагается, что он относится к тому же типу по контексту, он не пустой - хотя должен, и token действительно нужен тип string | undefined. Я полагаю, только const token = /…/.exec(auth)?.groups?.token делает это.

Bergi 24.04.2022 00:10

Извините, я как бы чувствую себя здесь в темноте, потому что я не знаю, чего я не знаю, но, возможно, это ответ на мой собственный вопрос: поскольку groups является типом { [key: string]: string; } | undefined, но ?? {} выводит тип как { [key: string]: string; } . Этот тип не допускает возможности отсутствия key или значения, поэтому все, что находится слева, считается string? Я правильно это понимаю? Я до сих пор не понимаю, почему ?? {} считается тем же типом, что и group, а не типом {}.

Daniel Kaplan 24.04.2022 00:30

Другие вопросы по теме

Передача vscode во внешние функции
Firebase: Почему мой код использует только первый документ в моей коллекции?
Реагировать на ошибку машинописного текста - элемент неявно имеет любой тип, потому что выражение строки типа не может использоваться для индексирования типа {}
Как получить доступ к вложенным необязательным индексам из интерфейса
Почему машинописный текст не может контекстуально вывести эти типы промежуточного программного обеспечения
Передать конструктор класса как функцию в другом классе
React & clsx: добавьте имя класса, если текущий элемент в сопоставленном массиве является первым из нескольких элементов
Свойство «MathFun» отсутствует в типе «(x?: число, y?: число) => число», но требуется в типе «Func».
Получение строки типа не может быть назначено строке типа для компонента TS в сборнике рассказов
Как ввести useState для файлов?