Статическая и динамическая типизация: плюсы, минусы, примеры
Основы3 минРедакция Innovialabs
Коротко
При статической типизации типы проверяются до запуска, при динамической — во время работы; сильная или слабая типизация — отдельный вопрос о неявных преобразованиях, а постепенная типизация (TypeScript, аннотации Python) позволяет взять лучшее от обоих подходов.
Коротко: две разные оси
Типизацию описывают двумя независимыми вопросами.
Когда проверяются типы?
- Статическая — до запуска, на этапе компиляции или анализа. Примеры: Java, C#, Go, Rust, TypeScript.
- Динамическая — во время выполнения, когда код доходит до конкретной строки. Примеры: Python, JavaScript, Ruby, PHP.
Насколько язык терпим к смешиванию типов?
- Сильная — неявных преобразований мало, сложить строку и число нельзя без явного приведения. Пример: Python.
- Слабая — язык охотно преобразует типы сам. Пример: JavaScript, где
"5" * 2даёт10.
Это разные оси: Python — динамический и сильный, JavaScript — динамический и слабый, Java — статический и в основном сильный. Термины «сильная/слабая» не имеют строгого определения, поэтому говорите о конкретном поведении, а не о ярлыке.
Одна ошибка — три языка
Функция считает итог заказа, а цена пришла из формы строкой.
JavaScript (динамический, слабый):
function total(price, qty) {
return price + qty;
}
total("100", 2); // "1002" — без ошибки, просто неверный результат
Ошибка тихая: программа продолжает работать с мусорными данными.
Python (динамический, сильный):
def total(price, qty):
return price + qty
total("100", 2) # TypeError: can only concatenate str (not "int") to str
Ошибка будет, но только когда код выполнится — возможно, уже у пользователя.
TypeScript (статический):
function total(price: number, qty: number): number {
return price + qty;
}
total("100", 2);
// Ошибка компиляции: Argument of type 'string'
// is not assignable to parameter of type 'number'.
Ошибка видна в редакторе ещё до запуска.
Плюсы и минусы
| Статическая | Динамическая | |
|---|---|---|
| Когда находятся ошибки типов | до запуска | во время работы |
| Подсказки и автодополнение в IDE | точные | ограниченные |
| Рефакторинг | безопаснее: компилятор покажет, что сломалось | нужны тесты, чтобы ничего не пропустить |
| Скорость старта проекта | больше кода на описание типов | быстрее писать прототип |
| Гибкость | ниже, иногда приходится «уговаривать» систему типов | высокая |
| Типы как документация | встроена в код | нужно читать реализацию или комментарии |
Ни один вариант не заменяет тесты: типы ловят несоответствие форм данных, но не неверную бизнес-логику.
Постепенная типизация: середина
Gradual typing позволяет добавлять типы постепенно, только туда, где они нужны.
- TypeScript — надстройка над JavaScript. Можно начать со свободного кода и ужесточать проверки через настройку
strict. - Python type hints — аннотации, которые интерпретатор не проверяет, но их проверяют mypy, pyright и IDE.
def total(price: float, qty: int) -> float:
return price * qty
total("100", 2) # mypy: Argument 1 has incompatible type "str"
Так делают многие команды: прототип пишется быстро, а по мере роста проекта типы добавляются в ключевые модули — API, модели данных, общие утилиты.
Как выбрать
- Небольшой скрипт, эксперимент, разовая задача — динамический язык без аннотаций вполне подходит.
- Проект, который будут развивать годами несколько человек — статическая или постепенная типизация заметно упрощает поддержку и рефакторинг.
- Уже есть большая кодовая база на JS или Python — не переписывайте всё, включайте типы поэтапно, начиная с границ системы.
Частые ошибки
- Включить TypeScript и везде писать
any— проверка формально есть, фактически нет. - Считать, что раз код скомпилировался, он работает правильно.
- Добавить аннотации в Python и не запускать проверку типов в CI — тогда они быстро устаревают.