Основы
Что такое TypeScript и как он связан с JavaScript, объявление переменных, const против let и вывод типов.
8 вопросов
JuniorТеорияОчень частоВ чём разница между const и let в TypeScript?
В чём разница между const и let в TypeScript?
const запрещает переприсваивание привязки после инициализации, а let допускает переприсваивание. const не делает значение глубоко неизменяемым — вы по-прежнему можете менять свойства const-объекта или делать push в const-массив, потому что фиксируется только ссылка. Оба имеют блочную область видимости. Для настоящей неизменяемости используйте readonly, as const или Object.freeze.
Типичные ошибки
- ✗Считать, что
constделает значение глубоко неизменяемым, тогда как он фиксирует лишь привязку, а не содержимое - ✗Думать, что
const-массив или объект нельзя менять, хотяpushи запись свойств всё ещё работают - ✗Полагать, что
constиletразличаются областью видимости — оба блочные, область функции только уvar
Уточняющие вопросы
- →Как сделать значение по-настоящему неизменяемым в TypeScript?
- →Почему всё ещё можно делать
pushв массив, объявленный черезconst?
JuniorТеорияЧастоКогда писать явную аннотацию типа вместо того, чтобы положиться на вывод типов?
Когда писать явную аннотацию типа вместо того, чтобы положиться на вывод типов?
Полагайтесь на вывод для локальной переменной с инициализатором — аннотация лишь повторяет выведенное компилятором. Аннотируйте там, где выводу нечего читать: параметры функций и пустой инициализатор вроде const xs: string[] = []. Тип возврата экспорта фиксируйте явно.
Типичные ошибки
- ✗Аннотировать локальную переменную с инициализатором, повторяя то, что уже вывел компилятор
- ✗Ждать, что тип параметра выведется из того, как его использует тело функции
- ✗Оставлять выведенным тип возврата экспортируемой функции, из-за чего рефакторинг молча меняет публичный контракт
Уточняющие вопросы
- →Почему параметр функции без аннотации — ошибка при включённом
noImplicitAny? - →Какой тип получает пустой литерал массива и почему это проблема?
JuniorТеорияЧастоКак объявлять переменные в TypeScript?
Как объявлять переменные в TypeScript?
Объявляйте переменные через let, const или var, при желании добавляя аннотацию : Type, например let count: number = 0. Если аннотация опущена, тип выводится из инициализатора. var имеет область видимости функции и поднимается, а let и const имеют блочную область видимости. Предпочитайте const, затем let, и избегайте var.
Типичные ошибки
- ✗Утверждать, что
letиconstимеют область видимости функции — у них блочная область, область функции только уvar - ✗Думать, что аннотация
: Typeобязательна, тогда как опущенная выводится из инициализатора - ✗Считать, что аннотация сохраняется в рантайме, хотя она стирается при компиляции
Уточняющие вопросы
- →Когда TypeScript выводит тип переменной вместо того, чтобы требовать аннотацию?
- →Почему
varне рекомендуют по сравнению сletиconst?
JuniorТеорияЧастоЧто такое TypeScript и чем он отличается от JavaScript?
Что такое TypeScript и чем он отличается от JavaScript?
TypeScript — это статически типизированное надмножество JavaScript от Microsoft. Он добавляет необязательные аннотации типов, проверяемые при компиляции, поэтому ошибки типов ловятся до запуска кода, и любой валидный JS является валидным TS. Он не запускается напрямую в браузере или Node — tsc транспилирует его в обычный JavaScript и стирает типы.
Типичные ошибки
- ✗Думать, что TypeScript исполняется в браузере напрямую, а не транспилируется в JavaScript через
tsc - ✗Считать, что аннотации типов сохраняются в рантайме и проверяются во время работы программы
- ✗Полагать, что валидный JavaScript нужно переписывать для TypeScript, хотя любой валидный JS уже является валидным TS
Уточняющие вопросы
- →Что значит, что типы TypeScript стираются после компиляции?
- →Почему любой валидный файл JavaScript также является валидным файлом TypeScript?
MiddleКодЧастоТипизируйте деструктурированный параметр и верните типизированный кортеж
Типизируйте деструктурированный параметр и верните типизированный кортеж
Аннотация вешается на весь шаблон, а не на имена внутри него: ({ host, retries = 3 }: { host: string; retries?: number }). Значение по умолчанию сужает retries в теле до обычного number. Возврату нужна явная аннотация : [string, number]: вывод расширяет литерал до (string | number)[].
Типичные ошибки
- ✗Писать
{ host: string }в шаблоне — это переименованиеhostвstring, а не типизация - ✗Ждать, что возвращаемый литерал массива выведется как кортеж
- ✗Думать, что default внутри шаблона всё равно оставляет имя с типом
T | undefined
Уточняющие вопросы
- →Что вместо этого даст
as constна возвращаемом литерале массива? - →Почему элемент деструктурированного массива теряет позицию без аннотации кортежа?
MiddleТеорияЧастоЧто такое вывод типов в TypeScript?
Что такое вывод типов в TypeScript?
Вывод типов — это автоматическое определение типа TypeScript по значению или контексту, когда аннотация не задана. let x = 10 выводит number, а тип возвращаемого значения функции выводится из её тела. Для массивов и объединений вычисляется наиболее общий тип, а контекстная типизация выводит тип параметра из ожидаемого типа. Это делает код лаконичным, сохраняя типобезопасность.
Типичные ошибки
- ✗Думать, что вывод происходит в рантайме, тогда как он полностью разрешается при компиляции проверщиком типов
- ✗Считать, что неаннотированная переменная становится
any, хотя вывод выводит конкретный тип из инициализатора - ✗Забывать, что
const x = 10выводит литеральный тип10, аlet x = 10выводитnumber
Уточняющие вопросы
- →Почему
const x = 10выводит10, аlet x = 10выводитnumber? - →Что такое контекстная типизация и когда она применяется?
MiddleТеорияИногдаЧто такое контекстная типизация и как она типизирует параметры коллбэка?
Что такое контекстная типизация и как она типизирует параметры коллбэка?
Контекстная типизация — вывод снаружи внутрь: тип, ожидаемый в позиции, задаёт типы записанному там выражению. В xs.map(x => x.length) аннотация для x не нужна — ожидаемый map тип параметра втекает в стрелку. Вынесите стрелку в const — и x станет неявным any.
Типичные ошибки
- ✗Ждать, что вынесенная в переменную стрелка сохранит типы параметров, которые были у неё на месте
- ✗Думать, что компилятор выводит тип параметра по тому, как его использует тело
- ✗Аннотировать параметры коллбэка, которые контекст уже типизировал
Уточняющие вопросы
- →Почему вынос коллбэка в
constдаёт ошибку о неявномany? - →Как явно переданный аргумент обобщённого типа меняет то, что задаёт контекст?
MiddleТеорияИногдаПочему let x = 'a' имеет тип string, а const x = 'a' — тип 'a'?
Почему let x = 'a' имеет тип string, а const x = 'a' — тип 'a'?
Потому что привязку let можно переприсвоить, и TypeScript расширяет её литеральный тип до базового string. Привязку const переприсвоить нельзя, поэтому литеральный тип 'a' сохраняется. То же расширение бьёт по изменяемым свойствам объекта: const o = { k: 'a' } даёт o.k тип string, и остановит это лишь as const.
Типичные ошибки
- ✗Ждать, что
const o = { k: 'a' }дастo.kлитеральный тип'a' - ✗Читать
constкак глубокую заморозку значения, а не как фиксацию привязки - ✗Не брать
as const, когда литеральный тип должен уцелеть внутри объекта
Уточняющие вопросы
- →Как
as constменяет тип вложенного объектного литерала? - →Почему передача
let mode = 'dark'в параметр'dark' | 'light'не проходит?