#typescript
Вопрос:
Как я могу создать тип строкового литерала как подтип другого типа строкового литерала?
Или, другими словами, как я могу выбрать значения из строкового литерального типа для создания нового типа?
Пример:
type Animal = 'goldfish' | 'tuna' | 'elephant'
// I would like to use Pick:
type Fish = Pick<Animal, 'goldfish', 'tuna'>
// So that the desired result is: 'goldfish | 'tuna'
Однако это не работает, потому что выбор работает только при выборе ключей свойств (объекта).
Комментарии:
1. Можете ли вы уточнить свои ограничения? Вы могли бы сделать это просто как отдельный литерал , подобный
type Fish = 'goldfish' | 'tuna';
, или как пересечение, подобноеtype Fish = Animal amp; ('goldfish' | 'lion');
.2. Я добавил желаемый результат к вопросу, возможно, это было не совсем ясно. Вы правы, я хочу
type Fish = 'goldfish' | 'tuna';
получить конечный результат, но я хочу выбрать значения,Animal
чтобы обеспечить соблюдение правильных значений.
Ответ №1:
Вместо Pick
этого ты можешь Extract
. Однако в данном случае со строковыми литералами это не продвинет вас дальше amp;
, чем.
type Fish = Extract<Animal, 'goldfish' | 'lion'> // 'goldfish'
type Fish2 = Animal amp; ('goldfish' | 'lion') // 'goldfish'
В обоих этих случаях обратите внимание, что это не будет ошибкой во время компиляции, если вы попытаетесь выбрать запись, которая не является частью исходного набора; она просто будет опущена. С помощью общих ограничений ( extends
) вы можете написать свой собственный Subset
тип, который выполняет эту задачу.
type Subset<K, T extends K> = T;
type Fish3 = Subset<Animal, 'goldfish' | 'lion'>; // compile error
type Fish4 = Subset<Animal, 'goldfish' | 'tuna'>; // 'goldfish' | 'tuna'
Комментарии:
1. Именно то, что мне нужно, спасибо, Джефф. Из любопытства, знаете ли вы, почему это не поддерживается встроенным типом утилиты? Типы строковых литералов популярны, и интуитивно я ожидаю, что они будут работать и для этого…
2. @rei Рад помочь! У меня нет хорошего ответа на вопрос, почему это не встроено, но, к счастью, это достаточно легко написать самостоятельно. Использование двух общих аргументов и возврат одного неизмененного немного необычно; если бы я предположил предложенную альтернативу, это было бы определить объединение строк без проверки, введите свои сайты вызовов как Animal и позвольте TS применять на сайте вызовов вместо определения типа. Конечно, это уводит ошибку от проблемы/исправления, поэтому, возможно, подмножество (или набор животных, если вы сделали конкретное) в этом случае все же лучше, за счет одной дополнительной строки кода для определения подмножества.