Что такое «сужение» в TS?
Прежде чем мы рассмотрим улучшение типов литералов в Typescript 4.5 и более поздних версиях, я просто хочу кратко повторить, что на самом деле означает «сужение» в этом контексте. По сути, вы можете сузить тип в Typescript, проверив свойства объекта. Если в сущности существует свойство, доступное только для определенного типа, TypeScript понимает это и, следовательно, может предоставить правильные типы.
Следующий пример кода демонстрирует, что я имею в виду.
type Addition = {
sum: number;
}
type Subtraction = {
result: number;
}
function calculate(action: Addition | Subtraction) {
if ('sum' in action) {
// Simple example of using properties
// of an entity to narrow down its
// actual type.
//
// 'action' is at this point of type
// 'Addition'. Nice!
const addition = action;
}
}
Сужение для типов строк шаблона
Начиная с Typescript версии 4.5, этот шаблон также можно применять к типам литералов шаблона, также известным как специальные строки с обратными кавычками. Сопоставление с образцом становится действительно мощным инструментом в языке.
Конечно, чтобы сужение стало пригодным для использования, все типы в сравнении должны иметь один и тот же ключ свойства. В противном случае вы можете просто использовать обычное сужение, как указано выше.
В следующем примере кода показано, как строки шаблона могут использовать сужение:
type Addition = {
variant: `${string}-addition`;
sum: number;
}
type Subtraction = {
variant: `${string}-subtraction`;
result: number;
}
function process(action: Addition | Subtraction) {
if (action.variant === "simple-addition") {
// Stupid simple example, but you get the idea:
// We used 'simple-addition', and the pattern
// matching by TS understood that '...-addition'
// can be discriminated to 'Addition'.
const addition = action;
}
}
//
// Example that DOES NOT work.
//
// This demo illustrates that the
// discriminante has to be a string,
// else the pattern matching worn't work.
type Addition = {
variant: `${string}-arithemtic`;
sum: number;
}
type Subtraction = {
variant: `${number}-arithemtic`;
result: number;
}
function process(action: Addition | Subtraction) {
if (action.variant === "123-arithemtic") {
// Still 'Addion | Subtraction',
// as we can only compare against
// a string '123-arithmetic', which
// is of course the same for both.
const addition = action;
}
}
А теперь вы знаете о сужении шаблонных литералов в Typescript! Это может быть функция, которую вы не будете использовать очень часто, но я думаю, что когда это уместно, она может значительно снизить сложность кода и сделать вашу базу кода немного чище, чем без этой функции.