Знакомство с оператором Satisfies в TypeScript

Знакомство с оператором Satisfies в TypeScript

1 ноября 2022 г.

<цитата>

Я знаю, что название поста глупое 😛, но позвольте мне заверить вас, как только вы узнаете, что делает оператор satisfies, вы получите контекст.

В бета-версии TypeScript 4.9 появился новый оператор satisfies. Оператор satisfies призван дать разработчикам возможность назначать наиболее конкретные типы выражений для вывода. Давайте посмотрим на это в действии.

Начнем с простого объекта

Предположим, что у нас есть цветной объект. Цветовой объект представляет значение цвета в RGB, то есть красный, зеленый и синий. Значение красного, зеленого и синего может быть строкой, шестнадцатеричным кодом, представляющим цвет #00ff00, или массивом из трех чисел, представляющим массив значений RGB. Три числа в массиве снова являются красными, зелеными и синими значениями. Структура объекта color представляет собой стандартный способ определения значений цвета.

// Color Object
const color = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [225, 255, 0],
};

Мы хотим иметь возможность вызывать методы массива для каждого из свойств объекта цвета. Поэтому, если мне нужно получить значение красного цвета по индексу 0, я смогу получить его, используя скобки.

const redComponent = color.red[0]; // 255

// Here, the constant `redComponent` should be equal to  `255`.  

Кроме того, поскольку значение любого из этих свойств может быть строкой, мы хотели бы иметь возможность использовать строковые методы для значений свойств, если это строка. Мы можем объявить другую константу, greenValue, и преобразовать значение зеленого цвета в верхний регистр.

const greenValue = palette.green.toUpperCase(); // '#00FF00'

//  The constant `greenValue` should be converted to upperCase like so '#00FF00'

Как сделать наш тип объекта безопасным

Пытаясь строго ввести объект цвета, мы должны помнить о приведенных выше случаях использования и следить за тем, чтобы свойства объекта не были написаны с ошибками, что означает красный, зеленый , и blue всегда должны быть написаны правильно. Typescript должен выдавать ошибку, если эти свойства указаны неправильно.

Для этого мы можем объявить тип с именем properties, который будет объединением красного, зеленого и синего цветов.

type Properties = 'red' | 'green' | 'blue';

Для значений каждого из этих свойств мы можем объявить тип RGB, который является кортежем. Кортеж — это массив, который имеет только три свойства: красный, зеленый и синий. Значения каждого свойства кортежа будут иметь тип number.

type RGB = [red: number, green: number, blue: number];

Теперь мы можем использовать тип Record, встроенный служебный тип в TypeScript, который создает объект с ключами и значениями для этих ключей.

const color: Record<Properties, RGB | string> = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [225, 255, 0],
};

Тип записи здесь гарантирует, что все свойства объекта цвета имеют тип Properties, а значения свойств представляют собой объединение типа RGB или string< /код>. Поэтому у нас не может быть свойства, которое не было бы ни красным, ни зеленым, ни синим. Поэтому, если я попытаюсь ошибиться в написании синего, TypeScript выдаст ошибку. Кроме того, все значения, присвоенные этим свойствам, теперь должны быть либо строковыми, либо RGB.

Проблема с этим подходом

На данный момент мы выиграли только половину битвы. Но есть проблема. Глядя на константу greenValue, мы видим, что TypeScript выдает ошибку. Мы получаем ошибку, потому что TypeScript не уверен в значении зеленого как строки или кортежа, и мы пытаемся использовать строковый метод для преобразования строки в верхний регистр. Если значение не является строкой, это приведет к ошибке. Чтобы использовать строковый метод, нам пришлось бы вручную проверять свойство, прежде чем мы сможем использовать такой строковый метод:

if (typeof color.green === 'string') {
  const greenValue = color.green.toUpperCase();
}

Представляем оператор satisfies

В таких ситуациях очень полезен новый оператор satisfies. Оператор satisfies выполняет предварительную проверку свойств объекта для нас. Мы можем удалить определение типа из объекта цвета и использовать оператор удовлетворения.

// Color Object
const color = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [225, 255, 0],
} satisfies Record<Properties, RGB | string>; 

Теперь оператор satisfies проверит для нас значения красного, зеленого и синего и проверит, содержит ли каждое из этих свойств строку или массив RGB. Так что теперь, даже если я удалю условие из константы greenValue, TypeScript не выдаст ошибку, потому что теперь он знает, что свойство green содержит строку, а не массив. Поскольку мы использовали оператор satisfies, TypeScript предварительно проверяет значения свойств объекта colors.

const greenValue = color.green.toUpperCase();

Точно так же, если я сейчас попытаюсь использовать строковый метод для значения синего, Typescript выдаст ошибку, потому что заранее знает, что синий — это массив чисел, а строковый метод нельзя применить к массиву чисел.

const blueValue = color.blue.toUpperCase();
// TypeScript Will throw an error  

Оператор satisfies делает за вас всю тяжелую работу и проверяет все значения, чтобы вам не приходилось вручную проверять каждое из значений объекта на предмет принадлежности к определенному типу, прежде чем использовать определенный метод для этого объекта. ценность. Если вы хотите изучить TypeScript, вам может быть интересно пройти мой ускоренный курс TypeScript на YouTube (https://www.youtube. com/watch?v=vcNtrYfroDY) или подписаться на другие подобные обновления и руководства.

Также опубликовано здесь

н


Оригинал