Статическая vs динамическая типизация: преимущества и выбор
Статическая типизация ️ – это когда ты заранее говоришь программе, какой тип данных (например, число или текст) будет использоваться. Это помогает избежать ошибок до того, как программа начнет работать.
Статическая типизация решает проблему несоответствия типов данных, которая может привести к ошибкам во время выполнения программы. Это делает код более предсказуемым и надежным, уменьшая шансы на сбои и упрощая отладку.
Это важно, потому что упрощает написание программ, делая их более эффективными и безопасными. Понимание разницы между статической и динамической типизациями помогает выбрать правильный инструмент для решения задачи, что критически важно для успешного завершения проектов.
Пример
Представьте, что вы строите дом из LEGO. У вас есть куча разных кирпичиков: красные, зелёные, большие, маленькие. Ваша задача – построить дом по инструкции, где чётко указано, куда и какой кирпичик должен быть установлен.
Статическая типизация в программировании работает похожим образом. Каждый «кирпичик» (переменная или функция) имеет свой тип, который определяется заранее и не меняется. Это как если бы вы заранее определили, что в определённое место дома можно поставить только красный кирпичик определённого размера.
Пример кода на Python с использованием аннотаций типов (Python поддерживает постепенную типизацию, что позволяет нам использовать статическую типизацию в динамическом языке):
Скопировать код
def add_numbers(a: int, b: int) -> int: return a + b result = add_numbers(5, 10) # Правильно, результат будет 15 # result = add_numbers("пять", "десять") # Ошибка! Мы ожидаем числа, а не строки.
В этом примере функция add_numbers ожидает два числа ( int ) и возвращает число ( int ). Если попытаться передать в неё строки, интерпретатор Python (если используется статический анализатор типов, например, mypy) выдаст ошибку ещё до запуска программы. Это помогает избежать ошибок во время выполнения и делает код более предсказуемым и безопасным.
Таким образом, статическая типизация помогает строить «дом» вашей программы более аккуратно и надёжно, указывая, какие «кирпичики» и куда вы можете ставить. Это уменьшает шанс ошибок и делает ваш код более читаемым для других разработчиков.
Почему статическая типизация может быть вашим лучшим выбором
Статическая типизация помогает обнаружить ошибки на ранней стадии разработки. Это значит, что ошибки типов данных обнаруживаются ещё до того, как программа будет запущена. Это может сэкономить массу времени и средств на этапе тестирования и отладки, особенно в больших и сложных проектах.
Преимущества статической типизации
- Повышение производительности: Компиляторы статически типизированных языков могут оптимизировать исполняемый код, зная точные типы данных заранее.
- Улучшение поддержки и автодополнения в IDE: Статическая типизация позволяет интегрированным средам разработки (IDE) предоставлять более точные предложения по автодополнению и рефакторингу кода.
- Лучшая читаемость и поддержка кода: Явное указание типов делает код более понятным для новых разработчиков в команде и упрощает поддержку существующего кода.
Примеры статически типизированных языков
Среди примеров статически типизированных языков можно выделить:
- Java: Широко используется для разработки крупномасштабных корпоративных систем и мобильных приложений на Android.
- C++: Применяется в системном программировании, разработке игр и высокопроизводительных приложений.
- Go: Популярен для разработки микросервисов и облачных приложений благодаря своей простоте и высокой производительности.
Когда динамическая типизация может быть лучшим выбором
Динамическая типизация предоставляет большую гибкость, позволяя переменным менять свой тип данных во время выполнения программы. Это может быть особенно полезно в сценариях, где заранее сложно определить, какие типы данных будут использоваться, например, при написании скриптов или прототипировании.
Преимущества динамической типизации
- Гибкость: Программисты могут быстрее писать код, не беспокоясь о строгом определении типов.
- Удобство для прототипирования: Быстрое изменение и тестирование различных подходов без необходимости перекомпиляции кода.
- Поддержка мощных техник программирования: Таких как метапрограммирование, которое может быть более сложным в статически типизированных языках.
Примеры динамически типизированных языков
- Python: Используется в веб-разработке, науке о данных, искусственном интеллекте и многих других областях.
- JavaScript: Основной язык для разработки интерактивных веб-сайтов.
- Ruby: Популярен в веб-разработке, особенно с фреймворком Ruby on Rails.
Постепенная типизация: сочетание лучшего из двух миров
Постепенная типизация предлагает гибкость динамической типизации при сохранении преимуществ статической типизации. Это позволяет разработчикам начать с динамической типизации в начале проекта для ускорения разработки и прототипирования, а затем постепенно добавлять статические типы для улучшения производительности и надежности кода.
Примеры языков с поддержкой постепенной типизации
- TypeScript: Надмножество JavaScript, добавляющее статическую типизацию в язык.
- Python: С версии 3.5 поддерживает аннотации типов, позволяя использовать статическую проверку типов.
Выводы
Выбор между статической и динамической типизацией зависит от множества факторов, включая специфику проекта, требования к производительности и предпочтения команды разработчиков. Важно помнить, что каждый подход имеет свои преимущества и может быть более подходящим в определённых ситуациях. Постепенная типизация предлагает интересный компромисс, позволяя разработчикам использовать преимущества обоих подходов в рамках одного проекта.
Динамическая типизация — Преобразование в Строку, Число и в Boolean type
Динамическая типизация — это возможность одного типа данных превращаться в другой.
Число может стать строкой, строка — числом. А объект — булевым значением.
Далее виды динамической типизации только те которые используются сейчас.
Преобразование в строку — to String
Динамическая типизация — преобразование в строку.
В JS если что то сложить со строкой, то это выражение превратится в строку.
Конкатенация — это сложение/объединение строк. Или сложение строки с чем-то: с каким-либо другим типом данных.
console.log('ww' + 'gg');
То есть две части строки спаялись в одну строку.
Прибавим к строке число.
console.log('ww' + 4);
К строке припаялась 4. И это уже не число, а строка. Для того что бы убедиться воспользуемся typeof .
console.log(typeof('ww' + 4));
Складывая с булевым значением все равно возвращается строка.
console.log(typeof('ww' + false));
Чаще всего что бы получить строку используют пустое значение в »
console.log(typeof('' + false));
Как конкатенацию применить на практике?
Самый простой и частый пример это формирование URL, так как это тоже строка. Допустим у вас есть какой то url и вам нужно перейти в catalog3 .
console.log('https://name.com/catalog' + 3);
Преобразование в число — to Number
Динамической типизация — Преобразование в число.
Унарный плюс более удобный способ конвертации различных типов данных в число, которым пользуются в настоящее время.
Унарный плюс конвертирует объект и строку в числовой тип данных.
Поставив перед любым типом данных + получим число number . Возьмем строку ‘5’ и преобразуем ее в число.
console.log(typeof(+'5'));
Методы parseInt()
Динамическая типизация с помощью данных методов встречается не часто, но используются для конвертации строк в числа.
console.log(parseInt('100px')); console.log(typeof(parseInt('100px')));
Где можно применить на практике типизация строки в число?
Все что получаете от пользователя — всегда будет типом данных строка string . Но предполагаем, что пользователь введет число и хотим получить тип данных именно число number .
let answ = +prompt(('Привет, сколько тебе лет?')); console.log(answ); console.log(typeof(answ));
Преобразование в булевы значения
Еще один вид динамической типизации — преобразование типов данных в булевы значения.
Например, null — Что это?
Истина или ложь: true или false ?
Логично предположить, что пустота или «не ничего» — это ложь. И это действительно так в языке JavaScript null — это false .
JavaScript всегда будет конвертироваться в ложь — false :
Строка, содержащая пробел ‘ ‘ — это уже не пустая строка(!)
Все остальное, что существует в JavaScript, в логическом контексте является истиной true .
В итоге получаем ничего или false . Продолжим код и переменной а присвоим 1
Типы и структуры данных JavaScript
Все языки программирования содержат встроенные типы данных, но они часто отличаются друг от друга в разных языках. Эта статья — попытка описать встроенные структуры (типы) данных, доступные в JavaScript, и их свойства. На их основе строятся другие структуры данных. Когда это возможно, то мы будем сравнивать типы данных в разных языках.
Динамическая типизация
JavaScript является слабо типизированным или динамическим языком. Это значит, что вам не нужно определять тип переменной заранее. Тип определится автоматически во время выполнения программы. Также это значит, что вы можете использовать одну переменную для хранения данных различных типов:
var foo = 42; // сейчас foo типа Number foo = "bar"; // а теперь foo типа String foo = true; // foo становится типа Boolean
Типы данных
Стандарт ECMAScript определяет 8 типов:
- 6 типов данных являющихся примитивами:
- Undefined (Неопределённый тип) : typeof instance === «undefined»
- Boolean (Булев, Логический тип) : typeof instance === «boolean»
- Number (Число) : typeof instance === «number»
- String (Строка) : typeof instance === «string»
- BigInt : typeof instance === «bigint»
- Symbol (en-US) (в ECMAScript 6) : typeof instance === «symbol»
И здесь нам необходимо сделать предостережение относительно использования оператора typeof для определения типа структур, т.к. все структуры будут возвращать «object» при его использовании, так как назначение typeof — проверка типа данных, но не структур. Если проверить тип структуры всё же необходимо, то в этом случае желательно использовать оператор instanceof, так как именно он отвечает на вопрос о том, какой конструктор был использован для создания структуры.
Стоит отметить два особых случая работы оператора typeof : возврат «object» для значения null и «function» для функций: первое принято считать ошибкой языка, сохраненной ради обратной совместимости, второе является условностью, удобной для проверки на принадлежность значения категории функций, где функция — это особый, «вызываемый», объект.
Примитивные значения
Все типы данных в JavaScript, кроме объектов, являются иммутабельными (значения не могут быть модифицированы, а только перезаписаны новым полным значением). Например, в отличии от C, где строку можно посимвольно корректировать, в JavaScript строки пересоздаются только полностью. Значения таких типов называются «примитивными значениями».
Булевый тип данных
Булевый тип представляет логическую сущность и имеет два значения: true (истина) и false (ложь) . Смотрите Boolean и Boolean для получения подробностей.
Null
Этот тип данных имеет всего одно значение: null . Смотрите null и Null для получения подробностей.
Undefined
Переменная, которой не было присвоено значение, будет иметь значение undefined . Смотрите undefined и undefined для получения подробностей.
Числа
В соответствии со стандартом ECMAScript, существует только один числовой тип, который представляет собой 64-битное число двойной точности согласно стандарту IEEE 754. Другими словами, специального типа для целых чисел в JavaScript нет. Это означает, что при числовых операциях вы можете получить неточное (округлённое) значение. В дополнение к возможности представлять числа с плавающей запятой, есть несколько символических значений: +Infinity (положительная бесконечность), -Infinity (отрицательная бесконечность), и NaN (не число).
Для получения самого большого или самого меньшего доступного значения в пределах +/-Infinity , можно использовать константы Number.MAX_VALUE или Number.MIN_VALUE . А начиная с ECMAScript 2015, вы также можете проверить, находится ли число в безопасном для целых чисел диапазоне, используя метод Number.isSafeInteger() , либо константы Number.MAX_SAFE_INTEGER и Number.MIN_SAFE_INTEGER . За пределами этого диапазона операции с целыми числами будут небезопасными, и возвращать приближённые значения.
Ноль в JavaScript имеет два представления: -0 и +0. («0» это синоним +0). На практике это имеет малозаметный эффект. Например, выражение +0 === -0 является истинным. Однако, это может проявиться при делении на ноль:
> 42 / +0 Infinity > 42 / -0 -Infinity
Хотя число в большинстве случаев представляет только своё значение, JavaScript предоставляет несколько бинарных операций. Они могут использоваться для того, чтобы представлять число как несколько булевых значений, с помощью битовой маски. Это считается плохой практикой, так как JavaScript предлагает другие способы представления булевых значений (например, массив элементов с булевыми значениями или объект, содержащий набор булевых свойств). Кроме того, битовые маски часто делают код более трудным для чтения, понимания и дальнейшей поддержки. Эта техника может быть необходима в условиях технических ограничений, таких как объём локального хранилища данных, или в такой экстремальной ситуации, когда каждый бит передаваемый по сети на счету. Данный подход следует использовать как крайнюю меру, когда не остаётся других путей для необходимой оптимизации.
Текстовые строки
В JavaScript для представления текстовых данных служит тип String . Он представляет собой цепочку «элементов» 16-битных беззнаковых целочисленных значений. Каждый такой элемент занимает свою позицию в строке. Первый элемент имеет индекс 0, следующий — 1, и так далее. Длина строки — это количество элементов в ней.
В отличие от языков подобных C, строки в JavaScript являются иммутабельными. Это означает, что после того, как строковое значение создано, его нельзя модифицировать. Остаётся лишь создать новую строку путём совершения некой операции над исходной строкой. Например:
- Получить часть исходной строки выборкой отдельных символов, либо применением метода String.substr() .
- Объединить две строки в одну, применив оператор ( + ) или метод String.concat() .
Избегайте повсеместного использования строк в своём коде!
Иногда может показаться соблазнительным использование строк для представления сложных структур данных. Это даст небольшие краткосрочные выгоды:
- Легко соединять данные в кучу сложением строк.
- Легко отлаживать (данные выглядят «как есть», в читаемом текстовом виде).
- Строки — это распространённый формат данных, используемый разнообразными API (поля ввода (en-US), значения локального хранилища, XMLHttpRequest возвращает ответ в виде строки, и т. д.) и использовать только строки может показаться заманчивым.
Несмотря на то, что в строке можно выразить данные любой сложности, делать это — не самая лучшая идея. Например, используя разделитель, строку можно использовать как список элементов (массив JavaScript будет более подходящим решением). К сожалению, если такой сепаратор встретится в значении одного из элементов, такой список будет сломан. Выходом может стать добавление символа экранирования, и т. д. Всё это потребует добавления множества ненужных правил, и станет обременительным при поддержке.
Используйте строки только для текстовых данных. Для составных структур преобразуйте строки в подобающие конструкции.
Тип данных Символ (Symbol)
Символы являются нововведением JavaScript начиная с ECMAScript 2015. Символ — это уникальное и иммутабельное примитивное значение, которое может быть использовано как ключ для свойства объекта (смотрите ниже). В некоторых языках программирования символы называются атомами. Их также можно сравнить с именованными значениями перечисления (enum) в языке C. Подробнее смотрите Symbol (en-US) и Symbol .
Тип данных Большое целое (BigInt)
BigInt является встроенным объектом, который предоставляет способ представления целых чисел, которые больше 2 53, что является наибольшим числом, которое JavaScript может надёжно представить с помощью Number примитива.
> let bigInt = 19241924124n; > console.log(bigInt); 19241924124n > console.log(typeof bigInt); "bigint"
Объекты
В компьютерной терминологии, объект — это значение в памяти, на которое возможно сослаться с помощью идентификатора.
Свойства
В JavaScript объект может расцениваться как набор свойств. Литеральная инициализация объекта задаёт определённое количество начальных свойств, и в процессе работы приложения поля могут добавляться и удаляться. Значения свойств могут иметь любой тип, включая другие объекты, что позволяет строить сложные, разветвлённые иерархии данных. Каждое свойство объекта идентифицируется ключом, в качестве которого может выступать значение с типом Строка или Символ.
Есть два типа свойств: свойство-значение и свойство-акцессор (свойство, обёрнутое в геттер и сеттер). Они отличаются определёнными атрибутами.
Свойство-значение
Ассоциирует ключ со значением, и имеет следующие атрибуты:
Атрибут Тип Описание Значение по умолчанию [[Value]] Любой тип JavaScript Значение, возвращаемое при обращении к свойству. undefined [[Writable]] Boolean Если false , то [[Value]] свойства не может быть изменено. false [[Enumerable]] Boolean Если true , свойство будет перечислено в цикле for. in. Смотрите подробнее Перечисляемость и владение свойствами. false [[Configurable]] Boolean Если false , то свойство не может быть удалено, а его атрибуты, кроме [[Value]] и [[Writable]] не могут быть изменены. false Атрибут Тип Описание Read-only Boolean Зарезервировано по атрибуту [[Writable]] ES5. DontEnum Boolean Зарезервировано по атрибуту [[Enumerable]] ES5. DontDelete Boolean Зарезервировано по атрибуту [[Configurable]] ES5. Свойство-акцессор
Ассоциирует ключ с одной из двух функций-акцессоров (геттер и сеттер) для получения или изменения значения свойства, и имеет следующий атрибуты:
Атрибут Тип Описание Значение по умолчанию [[Get]] Function или undefined Функция вызывается без параметров и возвращает значение свойства каждый раз, когда происходит чтение свойства. Смотрите также get (en-US) . undefined [[Set]] Function или undefined Функция вызывается с одним аргументом, содержащим присваиваемое значение, каждый раз, когда происходит попытка присвоить свойству новое значение. Смотрите также set (en-US) . undefined [[Enumerable]] Boolean Если true , свойство будет перечислено в цикле for. in. false [[Configurable]] Boolean Если false , то свойство не может быть удалено, и не может быть преобразовано в свойство-значение. false Примечание: Атрибуты обычно используются движком JavaScript, поэтому вы не можете обратиться к ним напрямую (смотрите подробнее Object.defineProperty()). Вот почему в таблицах выше они помещены в двойные квадратные скобки вместо одиночных.
«Обычные» объекты и функции
Объект JavaScript — это таблица соотношений между ключами и значениями. Ключи — это строки (или Symbol ), а значения могут быть любыми. Это делает объекты полностью отвечающими определению хеш-таблицы.
Функции — это обычные объекты, имеющие дополнительную возможность быть вызванными для исполнения.
Даты
Для работы с датами служит встроенный глобальный объект Date .
Массивы общие и типизированные
Массив — это обычный объект с дополнительной связью между целочисленными ключами его свойств и специальным свойством length. Вдобавок ко всему, массивы наследуют Array.prototype , предоставляющий исчерпывающий набор методов для манипуляции массивами. Например, метод indexOf (служит для поиска значения в массиве), push (en-US) (добавляет элемент в конец массива) и т. д. Всё это делает массив идеальным кандидатом для представления списков и перечислений.
Типизированные массивы являются подобными массивам представлениями наборов бинарных данных и предлагают множество методов, семантика которых аналогична аналогам массива. «Типизированный массив» это общий термин для ряда структур данных, включая Int8Array , Float32Array и т.д. Подробнее о них можно узнать в руководстве о типизированных массивах. Типизированные массивы часто используются вместе с ArrayBuffer и DataView .
Коллекции: Maps, Sets, WeakMaps, WeakSets
Эти наборы данных используют ссылку на объект в качестве ключа, и введены в JavaScript с приходом ECMAScript Edition 6. Set и WeakSet являют собой набор уникальных объектов, в то время как Map (en-US) и WeakMap ассоциируют с объектом (выступающим в качестве ключа) некоторое значение. Разница между Map и WeakMap заключается в том, что только у Map ключи являются перечисляемыми. Это позволяет оптимизировать сборку мусора для WeakMap.
Можно было бы написать собственную реализацию Map и Set на чистом ECMAScript 5. Однако, так как объекты нельзя сравнивать на больше или меньше, то производительность поиска в самодельной реализации будет вынужденно линейной. Нативная реализация (включая WeakMap) имеет производительность логарифмически близкую к константе.
Обычно, для привязки некоторых данных к узлу DOM, приходится устанавливать свойства этому узлу непосредственно, либо использовать его атрибуты data-* . Обратной стороной такого подхода является то, что эти данные будут доступны любому скрипту, работающему в том же контексте. Maps и WeakMaps дают возможность приватной привязки данных к объекту.
Структурированные данные: JSON
JSON (JavaScript Object Notation) — это легковесный формат обмена данными, происходящий от JavaScript, но используемый во множестве языков программирования. JSON строит универсальные структуры данных. Смотрите JSON и JSON для детального изучения.
Больше объектов и стандартная библиотека
JavaScript имеет стандартную библиотеку встроенных объектов. Пожалуйста, обратитесь к справочнику, чтобы найти описание всех объектов доступных для работы.
Определение типов оператором typeof
Оператор typeof может помочь определить тип вашей переменной. Смотрите страницу документации, где приведены его детали и случаи использования.
Смотрите также
- Nicholas Zakas, коллекция некоторых классических структур данных и алгоритмов, написанных на JavaScript.
- Реализация некоторых структур данных для JavaScript
Строгая типизация: Typescript, Flow, Javascript — быть или не быть?
Согласно опросу Global Developer Hiring Landscape Survey report 2017, проведенному Stack Overflow, JavaScript является самым востребованным языком программирования среди веб-разработчиков по всему миру. С момента своего создания в 1995 году JavaScript зарекомендовал себя как оптимальный язык работы с интерфейсами для браузеров и веб-страниц. Благодаря богатому набору библиотек он также обеспечил новые возможности для визуализации. Angular[.js], Ember.js и другие подобные фреймворки предоставили JS необходимую гибкость и возможности.
История JavaScript
Mosaic от NCSA был первым общепризнанным веб-браузером еще в 1993 году. А в 1994 Netscape представила свой популярный запатентованный браузер, получивший название Netscape Navigator, который считался единственным надежным вариантом в 90-х годах. Netscape наняла Брендана Эйха в 1995 году, и в том же году им был основан JavaScript. По словам Эйха:
«Мы стремились предоставить «язык-клей» для веб-дизайнеров и программистов на неполный рабочий день, которые строят веб-контент из таких компонентов, как изображения, плагины и мини-приложения на Java. Мы рассматривали Java как «компонентный язык», используемый более дорогостоящими программистами, где «программисты-склейщики» — разработчики веб-страниц — собирали бы компоненты и автоматизировали их с помощью JS».
Допустим. Мы находимся в сложном положении, когда большинство продвинутых языков переходят к функциональному программированию, к строгой и статической типизации.
JavaScript динамически типизированный язык и позволяет объявлять функции, объекты и переменные без объявления типа. Хотя эта возможность и упрощает использование языка, это не всегда удобно. Чтобы помочь справиться с такими проблемами типизации языков программирования, и появлялись TypeScript и Flow.
Цель статьи – выделить плюсы и минусы статической типизации в контексте разработки на Javascript. В дополнение к этому мы рассмотрим TypeScript и Flow, а также сравним их, чтобы в конце этой статьи вы могли бы решить: стоит ли переносить свои проекты на строгую типизацию вместо того, чтобы полагаться на «ванильный JavaScript».
Зачем это нужно
Вспомните Coffeescript, который был чрезвычайно популярен. Но, хотя я очень уважаю его изобретателя, факт заключается в том, что у этого языка были некоторые серьезные проблемы (почитайте соответствующую ветку переписки на ycombinator). Затем появился ES6.
Из-за необходимости поддерживать старые браузеры и для интерактивного выхода функционала ES6 у нас стали появляться транспайлеры, такие как Babel. Coffeescript имеет много общего с ним и тоже является транспайлером.
Инструментов CoffeeScript и Babel было недостаточно, что подтолкнуло сообщество в строну TypeScript и Flow. Взгляните на тренды (за Flow не ручаюсь, думаю, что возникла контекстуальная ошибка, он должен быть в несколько раз меньше).
Статистика Google Trends
TypeScript – это язык программирования с открытым исходным кодом, разработанный Microsoft, является суперсетом JS. По другую сторону – Flow, который разработан Facebook.
На практике Flow сравнительно проще, чем TypeScript, и его можно постепенно включить в файл проекта, настроить проверку типа в нем, просто добавив // @flow в начале файла. Все расширения основываются на комментариях.
Flow vs Typescript — сходства и отличия
Конечно, и TypeScript, и Flow полезны. Мы, в свою очередь, развернем сравнение с точки зрения разработчика.
TypeScript
TypeScript, как видно по названию, умеет проверять типизацию. Он принимает на вход (.ts) и генерирует (.js) на выходе. Существует флаг компилятора nolmplicitAny, который, если включен, потребует от вас указать типы и возвращаемые значения для всех используемых аргументов и функций.
Активация noImplicitAny может иметь серьезные последствия для вашей работы, особенно при работе с малоизвестными сторонними модулями. Помимо того, я обратил внимание, что при использовании noImplicitAny я стал писать часть кода специально, чтобы сделать довольным компилятор TypeScript.
Доступно множество описаний интерфейсов для библиотек JS. Если говорить о чем-то популярном, то проблем у вас не будет. Однако, нет уверенности, что разработчик, который написал файл .d.ts, сделал это аккуратно. Плюс ко всему, вам потребуется предоставить определение типов, если вы хотите внедрить стороннюю библиотеку для вашей кодировки. Готовьтесь заплатить за строгую типизацию своим временем.
В дополнение ко встроенной демонстрации ошибок до компиляции, при использовании TypeScript с IDE на подобии WebStorm перед вами откроется перекрестная навигация и более точное автозаполнение.
Flow
В отличие от TypeScript, Flow лишь сканирует ваши .js-файлы для обнаружения возможных ошибок. Другими словами, он действует как умный линтер.
Если пользуетесь Flow, то обратите внимание на пакет для Atom Nuclide.
Все же, кто на вершине?
Независимо от того, кто является вашим фаворитом: TypeScript или Flow, проверка типов – это будущее JS. Примечательным различием между Flow и TypeScript является то, насколько плавно они могут быть интегрированы в текущие проекты. В то время как TypeScript значительно сложнее, Flow относительно легко внедряем, предупреждая по ходу базовой интеграции, что проверяет меньше вашего кода, как и ожидается. Если вы пишете на Angular, то выбор у вас небольшой.
В дополнение ко всему, есть множество других аспектов, о которых стоит задуматься. В сочетании со статической типизацией, TypeScript также нацелен на предоставление гибкого набора инструментов, языковой поддержки рефакторинга и автокомплита.
Преимущества использования статической типизации
Обнаружение ошибок на лету
С помощью тестирования типов легко проверить работоспособность кода еще до его выполнения.
Следующие операции действительны в JavaScript, но вы получите бонус в typescript, например:
static.ts hosted with ❤ by GitHub
Более точная передача смысла функции
Типы действуют как активная, живая документация для автора и его тим-мейтов. Благодаря статической типизации вам легче понять цель функции, тип данных, которые он принимает в качестве входных, или что ожидать взамен.
Если вы считаете, что включение комментариев может сделать то же самое, вы не ошибаетесь. Но поскольку комментарии являются довольно подробными, они нарушают общую структуру кода, уменьшают полезную плотность. Комментарии — это следствие того, что вы не справились с передачей смысла кода в синтаксисе его языка (интересная книга на эту тему: Чистый код Роберта Мартина).
Упрощение отладки ошибок
Нам лучше проверить, что s – строка, а y – регулярное выражение. Без статических типов вам понадобится дополнительный код. А без него нас могут ждать сюрпризы во время выполнения.
Различие между данными и поведением
Поскольку статические типы четко различают данные и поведение, это позволяет разработчикам более уверенно прогнозировать свои ожидания и более точно объяснять цель. Это не только смягчит давление и двусмысленность, но также добавит ясности и прозрачности во время кодинга.
pressure.ts hosted with ❤ by GitHub
Сокращение вероятности возникновения ошибок во время выполнения
Ошибки типа во время выполнения становятся катастрофическими, на чем и живут такие сервисы как Sentry.
Например, приведенный ниже код будет работать в JavaScript, но будет отмечать ошибку компиляции: строка не существует.
helloworld.js hosted with ❤ by GitHub
Инструмент доменного моделирования (если использовать IDE)
Одна из лучших особенностей статических типов. Если вы работали в Visual Studio на языке подобном C#, вы поймете, о чем я. Это реально уменьшает административную сложность. Пример (у вас реально получится работать с субдоменами):
Недостатки использования статических типов
Проверка статического типа не лишена недостатков. Мы пройдемся по некоторым недостаткам, которые заслуживают внимания, прежде чем вы сделаете выбор в пользу статической типизации для своих проектов.
Одна из проблем – дополнительная стоимость обучения инженеров и затраты на сопровождение типизированного кода.
Одна из причин, по которой JavaScript настолько популярен среди веб-разработчиков, заключается в его простоте и в том, что им не нужно добираться до полной системы типов перед началом работы. Это особенно важно для начинающих программистов. Включение типов в процесс скорее запутает их и сделает процесс обучения более сложным, чем ожидалось.
С использованием TypeScript или Flow общий размер кода увеличится на 30% как минимум. Плотность кода снижается. Это как Ruby или Java 🙂
Использование статических типов в JavaScript — Да или Нет?
Выбор сводится к личным предпочтениям и типу проекта, над которым вы работаете. В заключение вы можете выбрать проверку статического типа, если:
- Достаточно большой и комплексный проект
Если ваша команда работает над проектом с большой базой кода, TypeScript поможет обойти множество ошибок. А лучше, чтобы эта база кода сейчас была маленькой или вообще равнялась нулю, тогда вы сможете сократить затраты на интеграцию.
- Над задачей работает большая команда
Чем больше людей, тем сложнее контролировать, что они пишут. Вам легче переложить часть боли машине.
- Рефакторинг программы в перспективе
Используйте TypeScript, если вы считаете, что в будущем потребуется большой рефакторинг. Не взваливайте на себя ненужное бремя, если имеете дело с краткосрочным заданием.
- Ваша команда знакома со статически типизированным языком
Строго типизированные языки, такие как TypeScript, – это прекрасный выбор, если вы или ваши товарищи по команде уже знакомы с типизированными языками, такими как Java или
C# обучением. Так как TypeScript был разработан тем же разработчиком, который изобрел C#, оба эти языка имеют похожие элементы.
TS+ES6 возможно перевести на ES5 с помощью TS-транспайлера. Вы сможете отказаться от babel.
- Библиотека/фреймворк предлагает TypeScript
Для тех, кто использует Angular 2+ или любой другой фреймворк, предлагающий TypeScript, следует попробовать статическую типизацию.
В заключение
Как только вы полноценно перейдете к статической типизации, то вряд ли вернетесь назад. Однако все это зависит от требований и объема проекта, над которым ведется работа. Не стесняйтесь поделиться своими мыслями, оставляйте комментарии. Мы будем рады услышать ваше мнение :).
Олександр Книга, Software Engineer в Weblab Technology
Дмитрий Дмитриенко, Brand Specialist в Weblab Technology
Шармин Хаят, Data Specialist в Weblab Technology