#typescript #webstorm
#машинописный текст #webstorm
Вопрос:
У меня есть структура данных (это может быть массив или объект), которая содержит некоторые данные настроек. В настоящее время это выглядит так:
const settings = [
{name: 'Albert', value: 'a', isDefault: true},
{name: 'Bradley', value: 'b'}
] as const
и тип
type TAllValues = settings[number]['value'] // is 'a' | 'b' <-- that Union Type is what I want
Что я надеюсь сделать, так это иметь возможность фильтровать этот список, чтобы получить подмножество на основе условия соответствия в настройке. Что-то вроде этого
type TDefaultValues = FilterSettings<settings, {isDefault: true}> // would be just 'a'
где я могу передать type
значение, имеющее эту форму, condition
и получить тип объединения значений для тех записей, которые соответствуют условию.
Я также мог бы изменить структуру данных на объект, если бы это помогло:
const settings = {
a: {name: 'Albert', isDefault: true},
b: {name: 'Bradley'}
}
Редактировать
Примечание — Существует проблема с WebStorm, которая по-разному обрабатывает определенные объединения. Я не выяснил, почему это было бы, но Barkers
и Barkers2
одинаковы во всех других средах, которые я пробовал. В Webstorm использование расширений для подмножества объекта из «как const» равно false , везде это true .
const Animals = [
{ animal: 'cat', bark: false },
{ animal: 'dog', bark: true }
] as const
type TAnimals = typeof Animals[number]
type TAnimals2 = { animal: 'cat'; bark: false } | { animal: 'dog'; bark: true }
type Barkers = Extract<TAnimals, { bark: true }> // <--- never
type Barkers2 = Extract<TAnimals2, { bark: true }> // <--- correct
Ответ №1:
Вы можете использовать распределительный условный тип, чтобы проверить, соответствует ли настройка условию, и выбрать только те, которые соответствуют:
const settings = [
{ name: 'Albert', value: 'a', isDefault: true },
{ name: 'Bradley', value: 'b' }
] as const
type Setting = typeof settings[number]
type FilterSettings<Condition, S extends Setting = Setting> =
S extends Condition ? S["value"] : never
type TDefaultValues = FilterSettings<{ isDefault: true }> // "a"
Комментарии:
1. Спасибо, это было большим подспорьем для обработки массива. Но я возвращаюсь
never
к TDefaultValues. Это работает, если я добавляю тип для SettingItemtype SettingItem = { name: string, value: string, isDefault?: boolean }
и пересекаюсь с нимtype Setting = typeof settings[number] amp; SettingItem
2. Вы можете увидеть, как это работает в прикрепленной игровой площадке. Я предполагаю, что тип
settings
, с которым вы тестируете, не такой, как в вопросе.3. Оказывается, в WebStorm все по-другому. Игровая площадка, проверка типов и VS-код одинаковы и работают так, как вы описали.
4. Хм, это странно. Попробуйте проверить, какая версия TS используется WebStorm (возможно, встроенная вместо установленной в node_modules)
5. Я согласен, это странно. Оба являются 4.5.2. Что может делать Webstorm? Я добавил проблему с intellij, и там была пара связанных. Это связано с тем, как создается тип объединения ‘to const’ / readonly по сравнению с литеральным — хотя я также подтвердил, что они оба
extends
разные. Возможно, наконец-то пришло время навсегда переключиться на VS Code.