← Усі теми

Питання на співбесіді з TypeScript з відповідями

Типи, дженерики, звуження, утилітарні та умовні типи, конфігурація і типізація React.

225 запитань для співбесіди з теми TypeScript з відповідями й поясненнями - рівні Junior, Middle і Senior. Приклади запитань, онлайн-тести й задачі на код.

Запитання за рівнями

Приклади запитань

Кілька запитань із кожного рівня з правильною відповіддю й поясненням.

TypeScript · Junior

  1. Що таке TypeScript?

    Правильна відповідь: Надмножина JavaScript зі статичною типізацією, що компілюється в JS

    Будь-який валідний JS - майже завжди валідний TS. Типи перевіряються під час компіляції, а потім стираються: у рантаймі виконується звичайний JavaScript, і перевірок типів там немає. Тому дані ззовні (API, форми) однаково валідують у рантаймі - наприклад, через Zod.

  2. Чи є перевірка типів TypeScript під час виконання програми?

    Правильна відповідь: Ні: типи стираються під час компіляції, у рантаймі працює звичайний JS

    TypeScript - інструмент часу розробки. Якщо API поверне null замість об'єкта, типи не врятують. Для рантайм-перевірок використовують typeof/instanceof і бібліотеки схем (Zod, Valibot), з яких можна вивести й TS-типи.

  3. Чим unknown відрізняється від any?

    Правильна відповідь: З unknown нічого не можна робити без звуження типу, а any вимикає перевірки

    any вимикає типізацію й «заражає» все, до чого торкається. unknown - безпечний аналог: значення може бути чим завгодно, але використовувати його можна лише після перевірки (typeof x === 'string'). Для даних із JSON.parse і catch (e) правильніше unknown.

  4. Що означає тип never?

    Правильна відповідь: Тип значення, якого не може бути: функція ніколи не повертає керування

    never - порожній тип. Його повертають функції, що завжди кидають виняток або зациклюються. Також він з'являється за повного звуження union-типу - на цьому побудована перевірка вичерпного switch. void - функція завершується, але результат не використовується.

Усі 75 запитань з відповідями →

TypeScript · Middle

  1. Що означає <T extends { id: string }> у дженерику?

    Правильна відповідь: Обмеження: T має мати принаймні властивість id: string

    Constraint дає змогу всередині функції безпечно звертатися до item.id, зберігаючи повний тип T у результаті. Передати можна будь-який об'єкт із відповідним id та іншими полями. Класи й успадкування тут ні до чого.

  2. Як типізувати функцію getProp(obj, key), щоб результат залежав від ключа?

    Правильна відповідь: function getProp<T, K extends keyof T>(obj: T, key: K): T[K]

    K extends keyof T дозволяє лише наявні ключі, а індексний доступ T[K] дає точний тип значення: getProp(user, 'age') → number. Варіант з any втрачає типізацію, а string пропустить помилку в назві.

  3. Що робить умовний тип T extends string ? 'text' : 'other'?

    Правильна відповідь: Обирає один із типів залежно від того, чи сумісний T зі string

    Умовні типи - «тернарник» на рівні типів. Разом з infer вони дають змогу видобувати частини типів. Застосовані до union, вони розподіляються по кожному члену (distributive conditional types).

  4. Що робить infer у type ElementType<T> = T extends (infer U)[] ? U : never?

    Правильна відповідь: Оголошує змінну типу U, яку TS виводить зі збігу з шаблоном

    infer використовується лише в extends-частині умовного типу: TS зіставляє T із шаблоном і «захоплює» потрібну частину. ElementType<string[]> → string. Так влаштовані ReturnType, Parameters, Awaited.

Усі 75 запитань з відповідями →

TypeScript · Senior

  1. Чи можна за strictFunctionTypes присвоїти (x: Dog) => void змінній типу (x: Animal) => void?

    Правильна відповідь: Ні: параметри функцій перевіряються контраваріантно

    Змінна обіцяє приймати будь-яке Animal, а функція вміє працювати лише з Dog - виклик із Cat зламається. Тому підтип за параметром іде у зворотний бік: (x: Animal) => void можна присвоїти туди, де чекають (x: Dog) => void, але не навпаки.

  2. Чому strictFunctionTypes не діє на метод, оголошений як handle(x: Dog): void?

    Правильна відповідь: Параметри методів (method syntax) перевіряються біваріантно заради сумісності

    Біваріантність методів залишили, щоб багато вбудованих типів (наприклад, Array<T>) лишалися сумісними. Якщо оголосити властивість-функцію handle: (x: Dog) => void, перевірка буде строгою. Тому для колбеків в інтерфейсах часто обирають синтаксис властивості.

  3. Чому дорівнює ToArray<string | number>, якщо type ToArray<T> = T extends any ? T[] : never?

    Правильна відповідь: string[] | number[]

    Умовний тип над «голим» параметром розподіляється по union: умова застосовується до кожного члена окремо. Це distributive conditional type - на ньому побудовані Exclude і Extract.

  4. Як вимкнути розподіл умовного типу по union?

    Правильна відповідь: Обгорнути обидві сторони в кортеж: [T] extends [U] ? X : Y

    Розподіл спрацьовує лише тоді, коли тип, що перевіряється, - «голий» параметр. Кортеж [T] робить його складеним, і union перевіряється цілком: [string | number] extends [string] → false. Налаштування компілятора для цього немає.

Усі 75 запитань з відповідями →

Збірні тести з цією темою

Запитання з кількох тем одразу - як на співбесіді на конкретну вакансію.

Задачі на код

Напишіть рішення просто в браузері - тести перевірять його одразу. Класика співбесід: debounce, throttle, deepClone, Promise.all, EventEmitter, LRU-кеш та інші.

Відкрити задачі →