В чем разница строгой и нестрогой типизации?
Что проверяют
Различаете ли вы две независимые оси: статическую и динамическую типизацию (когда проверяются типы) и сильную и слабую (разрешены ли неявные преобразования). Для фронтенда следом почти всегда идёт вопрос, что именно меняет TypeScript и почему он не спасает от приведения типов в рантайме.
Как отвечать
В русской речи термины плавают: «строгой» называют и сильную, и статическую типизацию. Сразу уточните, что вы понимаете под словом, и разведите оси:
- сильная (strong): язык не смешивает типы молча. В Python
"1" + 1даётTypeError, строку в число переводят только явно, черезint(); - слабая (weak): язык сам приводит типы. В JavaScript
"5" + 2равно"52","5" - 2равно3, а[] == falseвозвращаетtrue; - статическая: типы проверяются до запуска, при компиляции. Java, Rust, TypeScript;
- динамическая: тип привязан к значению и проверяется во время выполнения. JavaScript, Python.
Итог: у JavaScript слабая динамическая типизация, у Python сильная динамическая, у Java сильная статическая. Писать тип у каждой переменной при статической типизации не обязательно: TypeScript и Kotlin выводят его сами.
Про TypeScript скажите точно. Он добавляет статическую проверку, но при компиляции типы стираются, и поведение в рантайме остаётся от JavaScript. Данные с бэкенда, из localStorage или из формы он не проверит, для этого нужна валидация схемой, например через zod. Полезные настройки: "strict": true в tsconfig.json, unknown вместо any, === вместо ==.
Где спотыкаются
Называют Python языком со слабой типизацией. Он динамический, но сильный: сложить строку с числом не даст.
Думают, что TypeScript убирает неявные преобразования. "5" + 2 он спокойно пропустит и получит строку, а если значение пришло из API как any, проверки не будет вовсе.
Путают сильную типизацию с явными аннотациями и считают, что она требует прописывать тип у каждой переменной. Вывод типов прекрасно уживается со статикой.