В предыдущей части этой серии публикаций мы обсуждали безопасную возможность обнуления.
Теперь мы объясним и решим третью и последнюю проблему поведения TypeScript по умолчанию: остатки динамической типизации.
Мы рассмотрим:
TypeScript должен быть «средством проверки статического типа», в отличие от JavaScript, в котором набор текста является глубоко динамическим.
Но в предыдущей части этой серии статей мы также объяснили, что TypeScript создан как надмножество JavaScript.
Итак, проблема в следующем: некоторые части системы динамической типизации JavaScript остаются в TypeScript. Таким образом, мы собираемся объяснить, как подавить эти оставшиеся варианты поведения, чтобы добиться полной статической типизации.
Лучший пример проблемы — проверки на равенство. В JavaScript == — это не совсем проверка на равенство, а проверка эквивалентности:
1 == "1"; // true
Несмотря на то, что типы различаются, вступают в силу некоторые правила преобразования, поэтому JavaScript может сравнивать значения. Это может привести к множеству ошибок, поскольку детали правил трудно запомнить, иногда они довольно странные и не совсем одинаковы во всех динамических языках (например, в PHP).
Эти проверки эквивалентности имеют смысл только в динамически типизированном языке, таком как JavaScript. С того момента, как мы решим работать в TypeScript, следует использовать только фактические проверки на равенство (тип и значение).
1 === "1"; // false
Правило eqeqeq lint обеспечивает его соблюдение.
Людям, знакомым с такими языками, как Java, C# или Rust, следует быть особенно осторожными с этой проблемой, поскольку == в JavaScript или TypeScript не означает то же самое, что в этих языках. В JavaScript и TypeScript для достижения того же поведения требуется третий знак =.
Думаете, условия теперь безопасны? К сожалению, нет, поскольку преобразования могут быть неявными:
let tax: number | undefined = 0; if (tax) { console.log("Process payment"); } if (!tax) { throw new Error(); }
Приведенный выше пример эквивалентен:
let tax: number | undefined = 0; if (tax == true) { console.log("Process payment"); } if (tax == false) { throw new Error(); }
Как видите, здесь был неявный ==, поэтому преобразования все равно происходят: 0 не эквивалентен true, он эквивалентен false. Таким образом, произойдет ошибка, несмотря на то, что налог является допустимым значением.
Правило lint strict-boolean-expressions запрещает такие неявные условия и требует фактических проверок:
let tax: number | undefined = 0; if (tax !== undefined) { console.log("Process payment"); } if (tax === undefined) { throw new Error(); }
Возможно, это одно из самых утомительных правил для людей, привыкших к быстрым условиям в JavaScript, но если рассматривать его в перспективе, то это обычный способ делать что-то на других языках, таких как Java, C# или Rust.
Как показано в разделе конфигурации, отключение подпараметровallowNumber иallowString важно во избежание всех ошибок.
Единственное допустимое исключение — для объектов и массивов: эти случаи безопасны, поскольку, в отличие от строк и чисел, они не имеют ложных значений. Итак, следующее все еще в порядке:
let movie: Movie | undefined; if (movie) {} if (!movie) {}
Примечание: операторы переключения уже безопасны, поскольку внутри них используется ===.
Правило lint strict-boolean-expressions заботится о том, чтобы проверки условий были типобезопасными, но существуют и другие синтаксисы условий, кроме if:
const movieRating = userRating || 5; // Which is a shorter version of: const movieRating = userRating == true ? userRating : 5;
Если пользователь поставил оценку 0, 0 эквивалентно ложному, поэтому рейтинг будет 5 вместо 0.
Этого можно избежать с помощью современного JavaScript:
const movieRating = userRating ?? 5; // Which is a shorter version of: const movieRating = userRating !== undefined && userRating !== null ? userRating : 5;
Это может быть реализовано с помощью правила ворса предпочтения нулевого объединения.
Обратите внимание, что ?? не следует использовать везде: || по-прежнему актуален при работе с логическими значениями.
В JavaScript оператор можно использовать как для математического сложения чисел, так и для объединения строк. Это приводит к ошибке.
"There is " 3 1 "Matrix movies"; // 31 "There is " (3 1) "Matrix movies"; // 4
Оператор следует зарезервировать для математического сложения. Или, по крайней мере, его следует использовать только с данными одного и того же типа, что обеспечивает правило ограничения плюс операнды.
Для конкатенации строк следует использовать строки шаблонов из современного JavaScript, чего требует правило проверки предпочтительного шаблона:
const movie = `Everything everywhere all at once`; `${movie} is the best movie!`;
И наоборот, в строках шаблона следует использовать только строки, что требует правила lintstrict-template-expressions.
Если на самом деле требуется смешивание типов, преобразования должны быть явными:
const total = 3; `There is ${total.toFixed()} Matrix movies`;
Обратите внимание, что строки шаблона могут быть вложенными:
const total = 3; `There is ${total.toFixed()} Matrix movie${total > 1 ? "s" : ""}`;
Это конец этой серии постов. Вы можете подписаться на мою учетную запись (кнопка в правом верхнем углу этой страницы), чтобы узнать, когда публикуются другие сообщения о TypeScript или других темах, таких как Angular.
Вы хотите связаться со мной? Инструкции доступны в кратком описании.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3