├── .gitignore ├── assets ├── code.png └── typescript.svg ├── .github ├── FUNDING.yml ├── CONTRIBUTING.md └── PULL_REQUEST_TEMPLATE.md ├── .prettierrc ├── SECURITY.md ├── LICENSE.txt ├── CODE_OF_CONDUCT.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | #Junk 2 | .DS_Store 3 | .vscode/ 4 | .idea/ -------------------------------------------------------------------------------- /assets/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevLoversTeam/typescript-interview-questions/HEAD/assets/code.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # FUNDING.yml 2 | # Налаштування можливостей підтримки проєкту 3 | 4 | github: ViktorSvertoka 5 | buy_me_a_coffee: viktor.svertoka 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "useTabs": false, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "bracketSpacing": true, 8 | "arrowParens": "avoid", 9 | "proseWrap": "always" 10 | } 11 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🧠 Як зробити внесок у DevLovers 2 | 3 | Дякуємо, що хочете зробити внесок у наш проєкт! Нижче описано кілька простих правил, які допоможуть вам підготувати якісний pull request. 4 | 5 | ## 🔧 Формат доповнення 6 | 7 | - Кожне питання повинне бути оформлене в HTML-елементі `
` зі структурою: 8 | 9 | ![Code](../assets/code.png) 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Чекліст: 6 | 7 | - [ ] Я ознайомився з [CONTRIBUTING.md](CONTRIBUTING.md) і дотримувався вказівок. 8 | - [ ] Моє доповнення не дублює вже існуюче питання чи відповідь. 9 | - [ ] Я додав(ла) нове запитання у відповідному форматі (див. існуючі приклади). 10 | - [ ] Я додав(ла) нове запитання **в кінець файлу** з **наступним за порядком номером**. 11 | 12 | --- 13 | 14 | 15 | 16 | ... 17 | -------------------------------------------------------------------------------- /assets/typescript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # 🔒 Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you discover a security issue in any of my projects, I would greatly 6 | appreciate your help in resolving it responsibly. Here's how you can report it: 7 | 8 | 1. **Contact me:** 9 | Please send an email to 10 | **[devlovers.net@gmail.com](mailto:devlovers.net@gmail.com)** with: 11 | 12 | - A clear description of the issue. 13 | - Steps to reproduce the vulnerability. 14 | - Any relevant code or logs for better understanding. 15 | 16 | 2. **Handling process:** 17 | 18 | - I will acknowledge your report within **48 hours**. 19 | - Together, we will work on resolving the issue as quickly as possible. 20 | 21 | 3. **Confidentiality:** 22 | Please keep the details of the vulnerability private until it has been 23 | resolved. 24 | 25 | Your cooperation helps ensure the safety and security of my work. Thank you for 26 | contributing to a safer tech environment! 🙌 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 DevLovers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | [devlovers.net@gmail.com](mailto:devlovers.net@gmail.com). All complaints will 64 | be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | TypeScript 3 |

4 | 5 |

Найпопулярніші запитання та відповіді на співбесіді з TypeScript

6 | 7 | ### Основи TypeScript 8 | 9 |
10 | 1. Поясніть, що таке TypeScript та які його ключові відмінності від JavaScript. 11 | 12 | #### TypeScript 13 | 14 | **TypeScript** — це надбудова над JavaScript, яка додає статичну типізацію, 15 | інтерфейси та інші можливості для підвищення надійності коду. 16 | 17 | #### Відмінності: 18 | 19 | - **_Типізація:_** TS має статичні типи, JS — динамічні. 20 | 21 | - **_Розробка:_** TS виявляє помилки на етапі компіляції, JS — під час 22 | виконання. 23 | 24 | - **_Сумісність:_** TS компілюється у JS, тому працює у всіх середовищах JS. 25 | 26 | - **_Інструменти:_** краща підтримка IDE (автодоповнення, рефакторинг). 27 | 28 |
29 | 30 |
31 | 2. Що означає твердження, що TypeScript є надмножиною JavaScript? 32 | 33 | #### TypeScript 34 | 35 | - Це означає, що будь-який коректний JavaScript-код є також коректним 36 | TypeScript-кодом. TypeScript розширює можливості JS, додаючи типи та інші 37 | фічі, але при цьому не змінює базову мову. 38 | 39 |
40 | 41 |
42 | 3. Які основні вбудовані типи даних підтримує TypeScript? 43 | 44 | #### TypeScript 45 | 46 | **Основні типи в TypeScript:** 47 | 48 | - `string` — рядки 49 | 50 | - `number` — числа (цілі та з плаваючою крапкою) 51 | 52 | - `boolean` — логічні значення 53 | 54 | - `null` та `undefined` 55 | 56 | - `any` — будь-який тип 57 | 58 | - `unknown` — невідомий тип (безпечніша альтернатива any) 59 | 60 | - `void` — відсутність значення (часто у функціях) 61 | 62 | - `never` — функція ніколи не повертає значення (наприклад, кидає помилку) 63 | 64 | - `object` — об’єкти 65 | 66 | - `Масиви` (type[] або Array) 67 | 68 | - `Кортежі` ([type1, type2, ...]) 69 | 70 | - `enum` — перерахування 71 | 72 |
73 | 74 |
75 | 4. Які способи оголошення змінних у TypeScript та як до них застосовується типізація? 76 | 77 | #### TypeScript 78 | 79 | У TypeScript змінні оголошуються так само, як у JavaScript: `let`, `const`, 80 | рідше `var`. 81 | 82 | **Тип можна:** 83 | 84 | - вивести автоматично (Type Inference): 85 | 86 | ```TypeScript 87 | let age = 25; // type: number 88 | ``` 89 | 90 | - задати явно: 91 | 92 | ```TypeScript 93 | let age: number = 25; 94 | const name: string = "Alice"; 95 | ``` 96 | 97 | Зазвичай рекомендують використовувати `const` для незмінних значень, `let` для 98 | змінних, а явну типізацію — там, де виведення типу неочевидне. 99 | 100 |
101 | 102 |
103 | 5. Що таке інтерфейси в TypeScript і для чого вони використовуються? 104 | 105 | #### TypeScript 106 | 107 | Інтерфейси в TypeScript описують структуру об’єкта (його властивості та їх 108 | типи), не створюючи конкретної реалізації. Вони допомагають забезпечити контракт 109 | між частинами коду. 110 | 111 | **Основні можливості:** 112 | 113 | - Опис форми об’єкта: 114 | 115 | ```TypeScript 116 | interface User { 117 | id: number; 118 | name: string; 119 | isAdmin?: boolean; // необов’язкове поле 120 | } 121 | 122 | const user: User = { id: 1, name: "Alice" }; 123 | ``` 124 | 125 | - Підтримка опціональних властивостей (?). 126 | 127 | - Можливість розширення (extends). 128 | 129 | - Використання для опису структур функцій, класів та масивів. 130 | 131 | По суті, інтерфейси — це спосіб зробити код більш передбачуваним і безпечним. 132 | 133 |
134 | 135 |
136 | 6. Що таке enum у TypeScript та в яких випадках його доцільно використовувати? 137 | 138 | #### TypeScript 139 | 140 | - `enum` (перерахування) — це тип, який дозволяє задати набір іменованих 141 | констант. 142 | 143 | #### Види: 144 | 145 | - **Numeric enum** (значення автоматично інкрементуються): 146 | 147 | ```TypeScript 148 | enum Direction { 149 | Up, // 0 150 | Down, // 1 151 | Left, // 2 152 | Right // 3 153 | } 154 | ``` 155 | 156 | - **String enum:** 157 | 158 | ```TypeScript 159 | enum Role { 160 | Admin = "ADMIN", 161 | User = "USER", 162 | Guest = "GUEST" 163 | } 164 | ``` 165 | 166 | Використовується, коли є обмежений набір варіантів (напр. ролі користувачів, 167 | статуси замовлення, напрямки руху). Це робить код більш читабельним і безпечним, 168 | ніж "магічні числа" чи рядки. 169 | 170 |
171 | 172 |
173 | 7. Як правильно оголошувати та використовувати функції в TypeScript із врахуванням типів? 174 | 175 | #### TypeScript 176 | 177 | - Функції визначаються так само, як у JavaScript, але в TypeScript можна явно 178 | задавати типи параметрів і результату: 179 | 180 | ```TypeScript 181 | // З явними типами 182 | function add(a: number, b: number): number { 183 | return a + b; 184 | } 185 | 186 | // Функціональний вираз 187 | const greet = (name: string): string => { 188 | return `Hello, ${name}`; 189 | }; 190 | 191 | // Необов’язковий параметр 192 | function log(message: string, userId?: number): void { 193 | console.log(message, userId); 194 | } 195 | ``` 196 | 197 | - Параметри можна робити обов’язковими, необов’язковими (?) або мати значення за 198 | замовчуванням. 199 | 200 | - Тип повернення можна вивести автоматично, але для складних функцій краще 201 | вказувати явно. 202 | 203 | - Для callback-ів та складних сигнатур використовують типи або інтерфейси 204 | функцій. 205 | 206 |
207 | 208 |
209 | 8. Що таке виведення типу (type inference) у TypeScript і як воно працює? 210 | 211 | #### TypeScript 212 | 213 | - Виведення типу — це механізм, коли TypeScript автоматично визначає тип змінної 214 | чи результату функції на основі наданого значення без явного оголошення. 215 | 216 | #### Приклади: 217 | 218 | ```TypeScript 219 | let count = 10; // TS виводить: number 220 | let message = "Hi"; // TS виводить: string 221 | 222 | function add(a: number, b: number) { 223 | return a + b; // TS виводить: number (тип повернення) 224 | } 225 | ``` 226 | 227 | - Перевага: менше коду, але збережена типобезпека. 228 | 229 | - Ризик: у складних випадках краще явно вказувати тип, щоб уникнути 230 | неочікуваного any. 231 | 232 |
233 | 234 |
235 | 9. У чому різниця між let і const у TypeScript і як правильно їх використовувати? 236 | 237 | #### TypeScript 238 | 239 | `let` — дозволяє оголосити змінну, значення якої можна змінювати. Має блочну 240 | область видимості. 241 | 242 | `const` — створює змінну, якій можна призначити значення лише один раз. Також 243 | має блочну область видимості. 244 | 245 | #### Приклад: 246 | 247 | ```TypeScript 248 | let counter: number = 1; 249 | counter = 2; // ✅ можна 250 | 251 | const name: string = "Alice"; 252 | name = "Bob"; // ❌ помилка 253 | ``` 254 | 255 | Рекомендація: за замовчуванням використовувати `const`, а `let` — лише коли 256 | змінна дійсно змінюється. 257 | 258 | Важливо: `const` не робить об’єкт immutable, змінювати внутрішні властивості все 259 | одно можна: 260 | 261 | ```TypeScript 262 | const user = { id: 1, name: "Alice" }; 263 | user.name = "Bob"; // ✅ дозволено 264 | ``` 265 | 266 |
267 | 268 |
269 | 10. Яким чином можна скомпілювати TypeScript-файли у JavaScript? 270 | 271 | #### TypeScript 272 | 273 | - Використовується TypeScript Compiler (tsc). 274 | 275 | - Основні варіанти: 276 | 277 | ```bash 278 | # компіляція одного файлу 279 | 280 | tsc file.ts 281 | 282 | # компіляція проєкту з налаштуваннями tsconfig.json 283 | 284 | tsc 285 | ``` 286 | 287 | - У tsconfig.json можна задати цільову версію JS (target), директорію виводу 288 | (outDir), модулі (module) тощо. 289 | 290 | - Також можна включити watch mode: 291 | 292 | ```bash 293 | tsc -w 294 | ``` 295 | 296 | У реальних проєктах часто використовують Babel, Webpack, Vite чи ts-node для 297 | інтеграції компіляції у збірку чи запуск коду напряму. 298 | 299 |
300 | 301 | ### Класи та об'єкти в TypeScript 302 | 303 |
304 | 11. Що таке класи в TypeScript і чим вони відрізняються від класів у звичайному JavaScript? 305 | 306 | #### TypeScript 307 | 308 | Класи в TypeScript — це надбудова над JS-класами. Вони працюють так само, як у 309 | JS, але доповнені системою типів: 310 | 311 | - можна оголошувати типи для полів, параметрів і повертаних значень; 312 | 313 | - є модифікатори доступу (public, private, protected, readonly); 314 | 315 | - є abstract класи та методи; 316 | 317 | - підтримка implements для інтерфейсів; 318 | 319 | - підтримка generics. 320 | 321 | У рантаймі вони компілюються в звичайні JS-класи, а типи прибираються. 322 | 323 |
324 | 325 |
326 | 12. Як правильно реалізувати спадкування класів у TypeScript? 327 | 328 | #### TypeScript 329 | 330 | Використовується ключове слово `extends`. Базовий клас може мати загальні 331 | властивості/методи, похідний — успадковує їх і може перевизначати. При 332 | перевизначенні конструктора обов’язково викликається `super()`. 333 | 334 | ```TypeScript 335 | class Animal { 336 | constructor(public name: string) {} 337 | speak(): void { 338 | console.log(`${this.name} makes a sound.`); 339 | } 340 | } 341 | 342 | class Dog extends Animal { 343 | constructor(name: string, public breed: string) { 344 | super(name); 345 | } 346 | speak(): void { 347 | console.log(`${this.name} barks.`); 348 | } 349 | } 350 | 351 | const rex = new Dog("Rex", "Labrador"); 352 | rex.speak(); // Rex barks. 353 | ``` 354 | 355 |
356 | 357 |
358 | 13. Які є модифікатори доступу в TypeScript і як вони впливають на властивості та методи класів? 359 | 360 | #### TypeScript 361 | 362 | TypeScript має 4 модифікатори доступу: 363 | 364 | - `public` (за замовчуванням) – доступний скрізь. 365 | 366 | - `private` – доступний тільки всередині цього класу. 367 | 368 | - `protected` – доступний у класі та його нащадках. 369 | 370 | - `readonly` – властивість доступна тільки для читання після ініціалізації. 371 | 372 | Вони впливають лише на етапі компіляції (для контролю типів), у рантаймі 373 | JavaScript цього обмеження немає. 374 | 375 |
376 | 377 |
378 | 14. Що таке абстрактні класи в TypeScript і для чого їх використовують? 379 | 380 | #### TypeScript 381 | 382 | Абстрактний клас — це клас, який не можна інстанціювати напряму. Він може 383 | містити: 384 | 385 | - реалізовані методи, які спільні для всіх нащадків, 386 | 387 | - abstract методи без реалізації, які зобов’язані реалізувати похідні класи. 388 | 389 | Призначення: задавати загальний контракт і базову поведінку для групи класів, 390 | залишаючи конкретну реалізацію нащадкам. 391 | 392 | ```TypeScript 393 | abstract class Shape { 394 | constructor(public color: string) {} 395 | abstract area(): number; // має реалізувати підклас 396 | describe(): void { 397 | console.log(`This shape is ${this.color}`); 398 | } 399 | } 400 | 401 | class Circle extends Shape { 402 | constructor(color: string, public radius: number) { 403 | super(color); 404 | } 405 | area(): number { 406 | return Math.PI * this.radius ** 2; 407 | } 408 | } 409 | 410 | const c = new Circle("red", 5); 411 | c.describe(); // This shape is red 412 | console.log(c.area()); // 78.5398... 413 | ``` 414 | 415 |
416 | 417 |
418 | 15. Як працюють конструктори в класах TypeScript і які особливості їх використання? 419 | 420 | #### TypeScript 421 | 422 | Конструктор (constructor) — це метод для ініціалізації об’єкта класу. 423 | Особливості у TypeScript: 424 | 425 | - можна задавати типи параметрів; 426 | 427 | - можна використовувати модифікатори доступу прямо в параметрах (`public`, 428 | `private`, `protected`, `readonly`) — тоді TypeScript автоматично створює 429 | відповідні поля; 430 | 431 | - у похідних класах обов’язково викликається `super()` перед використанням 432 | `this`. 433 | 434 | #### Приклад: 435 | 436 | ```TypeScript 437 | class Person { 438 | constructor(public name: string, private age: number) {} 439 | greet() { 440 | console.log(`Hi, my name is ${this.name}`); 441 | } 442 | } 443 | 444 | class Employee extends Person { 445 | constructor(name: string, age: number, public position: string) { 446 | super(name, age); 447 | } 448 | } 449 | 450 | const emp = new Employee("Alice", 30, "Developer"); 451 | emp.greet(); // Hi, my name is Alice 452 | console.log(emp.position); // Developer 453 | ``` 454 | 455 |
456 | 457 |
458 | 16. Що таке декоратори в TypeScript для властивостей класу і як їх застосовувати? 459 | 460 | #### TypeScript 461 | 462 | Декоратори — це функції, які дозволяють змінювати або розширювати поведінку 463 | класів, методів, властивостей або параметрів. Декоратор властивості отримує ціль 464 | (target) та ім’я властивості (property key). 465 | 466 | **Приклад використання властивості:** 467 | 468 | ```TypeScript 469 | function logProperty(target: any, key: string) { 470 | let value = target[key]; 471 | 472 | const getter = () => { 473 | console.log(`Getting ${key}: ${value}`); 474 | return value; 475 | }; 476 | 477 | const setter = (newVal: any) => { 478 | console.log(`Setting ${key} to ${newVal}`); 479 | value = newVal; 480 | }; 481 | 482 | Object.defineProperty(target, key, { 483 | get: getter, 484 | set: setter, 485 | enumerable: true, 486 | configurable: true 487 | }); 488 | } 489 | 490 | class Person { 491 | @logProperty 492 | name: string = ""; 493 | } 494 | 495 | const p = new Person(); 496 | p.name = "Alice"; // Setting name to Alice 497 | console.log(p.name); // Getting name: Alice 498 | ``` 499 | 500 | Декоратори часто використовують для логування, валідації, DI (dependency 501 | injection) та метаданих. 502 | 503 |
504 | 505 |
506 | 17. Як реалізуються та працюють геттери (get) і сеттери (set) у TypeScript? 507 | 508 | #### TypeScript 509 | 510 | Геттери та сеттери дозволяють контролювати доступ до властивостей класу. 511 | 512 | - `get` — повертає значення властивості, дозволяє виконувати додаткову логіку 513 | при читанні. 514 | 515 | - `set` — задає значення властивості, дозволяє перевіряти або модифікувати його 516 | перед присвоєнням. 517 | 518 | #### Приклад: 519 | 520 | ```TypeScript 521 | class Person { 522 | private _age: number = 0; 523 | 524 | get age(): number { 525 | return this._age; 526 | } 527 | 528 | set age(value: number) { 529 | if (value < 0) throw new Error("Age cannot be negative"); 530 | this._age = value; 531 | } 532 | } 533 | 534 | const p = new Person(); 535 | p.age = 25; // викликається set 536 | console.log(p.age); // викликається get -> 25 537 | ``` 538 | 539 | Геттери і сеттери працюють як звичайні властивості при доступі, але дозволяють 540 | інкапсулювати логіку. 541 | 542 |
543 | 544 |
545 | 18. Як реалізується перевантаження методів у TypeScript? 546 | 547 | #### TypeScript 548 | 549 | TypeScript дозволяє перевантажувати методи через сигнатури, але тільки одна 550 | реалізація. Це означає: можна оголосити кілька варіантів виклику методу з 551 | різними параметрами, а в тілі методу реалізувати логіку з перевіркою 552 | типів/кількості аргументів. 553 | 554 | #### Приклад: 555 | 556 | ```TypeScript 557 | class Calculator { 558 | add(a: number, b: number): number; 559 | add(a: string, b: string): string; 560 | add(a: any, b: any): any { // реальна реалізація 561 | return a + b; 562 | } 563 | } 564 | 565 | const calc = new Calculator(); 566 | console.log(calc.add(2, 3)); // 5 567 | console.log(calc.add("Hello, ", "TS")); // Hello, TS 568 | ``` 569 | 570 | #### Особливості: 571 | 572 | - Сигнатури визначають дозволені варіанти виклику. 573 | 574 | - Реалізація повинна враховувати всі варіанти. 575 | 576 | - У рантаймі перевантаження як у C#/Java не існує, це чисто типізаційний 577 | механізм. 578 | 579 |
580 | 581 |
582 | 19. Для чого використовується ключове слово static у класах TypeScript? 583 | 584 | #### TypeScript 585 | 586 | `static` дозволяє створювати члени класу (властивості або методи), які належать 587 | самому класу, а не його екземплярам. 588 | 589 | - До них звертаються через ім’я класу (ClassName.member), а не через об’єкт. 590 | 591 | - Можна використовувати для констант, утилітарних методів та лічильників. 592 | 593 | #### Приклад: 594 | 595 | ```TypeScript 596 | class Counter { 597 | static count = 0; 598 | 599 | static increment() { 600 | Counter.count++; 601 | } 602 | } 603 | 604 | Counter.increment(); 605 | console.log(Counter.count); // 1 606 | 607 | const c = new Counter(); 608 | // c.increment(); // ❌ помилка, increment — static 609 | ``` 610 | 611 |
612 | 613 | ### Типи та приведення типів у TypeScript 614 | 615 |
616 | 20. Як створити власний тип у TypeScript за допомогою псевдоніму (type alias)? 617 | 618 | #### TypeScript 619 | 620 | Псевдонім типу (`type`) дозволяє створити нове ім’я для будь-якого типу, включно 621 | з об’єднаннями (`union`), перетинами (`intersection`) та функціями. Це зручно 622 | для складних типів, повторного використання і документації коду. 623 | 624 | ```TypeScript 625 | type ID = string | number; 626 | type User = { 627 | id: ID; 628 | name: string; 629 | age?: number; // необов’язкове поле 630 | }; 631 | 632 | type Callback = (result: string) => void; 633 | ``` 634 | 635 | Використовуємо як звичайний тип: 636 | 637 | ```TypeScript 638 | const user: User = { id: 1, name: "Alice" }; 639 | ``` 640 | 641 | Псевдоніми не створюють нових типів у рантаймі — це чисто типізація на етапі 642 | компіляції. 643 | 644 |
645 | 646 |
647 | 21. Що таке union-типи в TypeScript і як їх застосовувати? 648 | 649 | #### TypeScript 650 | 651 | Union-тип (|) дозволяє змінній або параметру приймати декілька можливих типів. 652 | Це зручно, коли значення може бути різного виду. 653 | 654 | #### Приклад: 655 | 656 | ```TypeScript 657 | type ID = string | number; 658 | 659 | function printId(id: ID) { 660 | if (typeof id === "string") { 661 | console.log("ID (string): " + id.toUpperCase()); 662 | } else { 663 | console.log("ID (number): " + (id * 10)); 664 | } 665 | } 666 | 667 | printId("abc"); // ID (string): ABC 668 | printId(123); // ID (number): 1230 669 | ``` 670 | 671 | #### Особливості: 672 | 673 | - Потрібно робити type narrowing (перевірку типу) перед використанням 674 | специфічних методів. 675 | 676 | - Можна комбінувати кілька типів, навіть `null | undefined`. 677 | 678 |
679 | 680 |
681 | 22. Що таке intersection-типи в TypeScript і як вони працюють? 682 | 683 | #### TypeScript 684 | 685 | Intersection-тип (&) поєднує кілька типів в один. Об’єкт повинен відповідати 686 | всім об’єднаним типам одночасно. Це зручно для створення складних структур з 687 | кількох контрактів. 688 | 689 | #### Приклад: 690 | 691 | ```TypeScript 692 | type Person = { name: string }; 693 | type Employee = { company: string }; 694 | type Developer = Person & Employee & { skills: string[] }; 695 | 696 | const dev: Developer = { 697 | name: "Alice", 698 | company: "TechCorp", 699 | skills: ["TypeScript", "React"] 700 | }; 701 | ``` 702 | 703 | #### Особливості: 704 | 705 | - Якщо є конфліктні властивості з різними типами → результат може стати never. 706 | 707 | - Добре поєднується з interface і type для композиції. 708 | 709 |
710 | 711 |
712 | 23. Що таке кортежі (Tuple types) у TypeScript і в яких випадках їх варто застосовувати? 713 | 714 | #### TypeScript 715 | 716 | Tuple — це масив із фіксованою кількістю елементів та визначеними типами для 717 | кожної позиції. Використовуються, коли порядок і типи елементів наперед відомі. 718 | 719 | #### Приклад: 720 | 721 | ```TypeScript 722 | let user: [number, string, boolean]; 723 | user = [1, "Alice", true]; // ✅ правильний порядок і типи 724 | user = ["Alice", 1, true]; // ❌ помилка 725 | ``` 726 | 727 | #### Особливості: 728 | 729 | - Можна додати назви для кращої читабельності: 730 | 731 | ```TypeScript 732 | type HttpResponse = [statusCode: number, message: string]; 733 | const res: HttpResponse = [200, "OK"]; 734 | ``` 735 | 736 | - Підтримують optional та rest елементи: 737 | 738 | ```TypeScript 739 | type RGB = [number, number, number?, number?]; // (R, G, B, A?) 740 | ``` 741 | 742 | Використовувати, коли треба передавати структуровані дані з фіксованим форматом 743 | (наприклад, координати, записи логів, HTTP-відповідь). 744 | 745 |
746 | 747 |
748 | 24. Що таке твердження типів (type assertions) у TypeScript і для чого вони потрібні? 749 | 750 | #### TypeScript 751 | 752 | Type assertion — це спосіб сказати компілятору: «повір мені, я знаю реальний тип 753 | цього значення». Це не змінює рантайм-поведінку, лише впливає на перевірку 754 | типів. 755 | 756 | #### Синтаксис: 757 | 758 | ```TypeScript 759 | let value: unknown = "Hello TS"; 760 | 761 | // спосіб 1 762 | let strLength: number = (value as string).length; 763 | 764 | // спосіб 2 (JSX несумісний, тому рідше) 765 | let strLength2: number = (value).length; 766 | ``` 767 | 768 | #### Навіщо це корисно: 769 | 770 | - коли TypeScript не може вивести точний тип; 771 | 772 | - при роботі з any або unknown; 773 | 774 | - при доступі до DOM-елементів: 775 | 776 | ```TypeScript 777 | const input = document.getElementById("username") as HTMLInputElement; 778 | console.log(input.value); 779 | ``` 780 | 781 | ⚠️ Важливо: це не "перетворення типів", а підказка компілятору. Якщо ви 782 | помилитеся, помилка проявиться вже у рантаймі. 783 | 784 |
785 | 786 |
787 | 25. Як працює перевірка типів за допомогою typeof у TypeScript і як її використовувати для type narrowing 788 | 789 | #### TypeScript 790 | 791 | `typeof` у TypeScript використовується для звуження union-типів під час 792 | виконання. Це type guard, який дозволяє компілятору зрозуміти, який тип у 793 | змінної в конкретній гілці коду. 794 | 795 | #### Приклад: 796 | 797 | ```TypeScript 798 | function printId(id: string | number) { 799 | if (typeof id === "string") { 800 | console.log("Uppercase ID:", id.toUpperCase()); // тут id: string 801 | } else { 802 | console.log("Numeric ID:", id.toFixed(2)); // тут id: number 803 | } 804 | } 805 | ``` 806 | 807 | #### Особливості: 808 | 809 | - `typeof` перевіряє типи рантайму: `string`, `number`, `boolean`, `object`, 810 | `function`, `undefined`, `symbol`, `bigint`. 811 | 812 | - Використовується у функціях для безпечної роботи з union-типами. 813 | 814 | Також typeof можна використовувати для отримання типу змінної чи функції при 815 | оголошенні: 816 | 817 | ```TypeScript 818 | let person = { name: "Alice", age: 30 }; 819 | type Person = typeof person; // { name: string; age: number } 820 | ``` 821 | 822 |
823 | 824 |
825 | 26. Чи можна в TypeScript створювати типи на основі існуючих даних (значень) за допомогою виведення типів? 826 | 827 | #### TypeScript 828 | 829 | Так, можна. TypeScript дозволяє виводити типи з існуючих значень за допомогою 830 | typeof і keyof. 831 | 832 | #### Приклади: 833 | 834 | 1. **Отримання типу з об’єкта** 835 | 836 | ```TypeScript 837 | const user = { 838 | id: 1, 839 | name: "Alice", 840 | isAdmin: true 841 | }; 842 | 843 | type User = typeof user; 844 | // User = { id: number; name: string; isAdmin: boolean } 845 | ``` 846 | 847 | 2. **Отримання типів ключів** 848 | 849 | ```TypeScript 850 | type UserKeys = keyof typeof user; 851 | // "id" | "name" | "isAdmin" 852 | ``` 853 | 854 | 3. **Комбінація з літеральними типами** 855 | 856 | ```TypeScript 857 | const roles = ["admin", "user", "guest"] as const; 858 | type Role = typeof roles[number]; 859 | // "admin" | "user" | "guest" 860 | ``` 861 | 862 | Це дозволяє уникати дублювання коду й гарантує синхронізацію типів з даними. 863 | 864 |
865 | 866 | ### Узагальнені типи (Generics) у TypeScript 867 | 868 |
869 | 27. Що таке узагальнені типи (Generics) у TypeScript і для чого вони потрібні? 870 | 871 | #### TypeScript 872 | 873 | **Generics** — це параметризовані типи, які дозволяють писати універсальний і 874 | багаторазовий код, зберігаючи типобезпеку. Вони дозволяють відкладати визначення 875 | конкретного типу до моменту використання. 876 | 877 | #### Приклад: функція без generics 878 | 879 | ```TypeScript 880 | function identity(value: any): any { 881 | return value; 882 | } 883 | ``` 884 | 885 | - Проблема: втрачається тип. 886 | 887 | #### Приклад з generics 888 | 889 | ```TypeScript 890 | function identity(value: T): T { 891 | return value; 892 | } 893 | 894 | let num = identity(42); // num: number 895 | let str = identity("Hello"); // str: string (TS вивів тип автоматично) 896 | ``` 897 | 898 | #### Generics у класах і інтерфейсах 899 | 900 | ```TypeScript 901 | class Box { constructor(public content: T) {} 902 | } 903 | 904 | const stringBox = new Box("TS"); // Box 905 | const numberBox = new Box(123); // Box 906 | ``` 907 | 908 | #### Навіщо: 909 | 910 | - Писати гнучкий і типобезпечний код (колекції, утиліти, API). 911 | 912 | - Уникати any і втрати інформації про тип. 913 | 914 | - Дозволяє зв’язати вхідний і вихідний типи. 915 | 916 |
917 | 918 |
919 | 28. Як правильно створити узагальнену (generic) функцію в TypeScript? 920 | 921 | #### TypeScript 922 | 923 | Узагальнена функція визначається через параметр типу в кутових дужках ``. Це 924 | дозволяє зберегти типобезпеку і не втрачати інформацію про тип. 925 | 926 | #### Базовий приклад 927 | 928 | ```TypeScript 929 | function identity(value: T): T { 930 | return value; 931 | } 932 | 933 | let n = identity(10); // n: number 934 | let s = identity("TS"); // s: string (тип виведено автоматично) 935 | ``` 936 | 937 | #### З кількома параметрами типів 938 | 939 | ```TypeScript 940 | function pair(first: T, second: U): [T, U] { 941 | return [first, second]; 942 | } 943 | 944 | const result = pair("id", 123); // [string, number] 945 | ``` 946 | 947 | #### З обмеженням типу (extends) 948 | 949 | ```TypeScript 950 | function getLength(item: T): number { 951 | return item.length; 952 | } 953 | 954 | getLength("Hello"); // 5 955 | getLength([1, 2, 3]); // 3 956 | getLength(42); // ❌ помилка, бо number не має length 957 | ``` 958 | 959 | Таким чином, generics роблять функції універсальними, але строго типізованими. 960 | 961 |
962 | 963 |
964 | 29. Як визначити узагальнені (generic) інтерфейси у TypeScript і для чого вони використовуються? 965 | 966 | #### TypeScript 967 | 968 | Узагальнені інтерфейси дозволяють описати контракт, який працює з різними 969 | типами, зберігаючи типобезпеку. Для цього в інтерфейс додають параметри типів 970 | `` (або кілька). 971 | 972 | #### Приклад: базовий generic-інтерфейс 973 | 974 | ```TypeScript 975 | interface Box { 976 | value: T; 977 | } 978 | 979 | const numBox: Box = { value: 42 }; 980 | const strBox: Box = { value: "Hello" }; 981 | ``` 982 | 983 | #### З кількома параметрами 984 | 985 | ```TypeScript 986 | interface Pair { 987 | key: K; 988 | value: V; 989 | } 990 | 991 | const pair: Pair = { key: "age", value: 30 }; 992 | ``` 993 | 994 | #### Узагальнені інтерфейси з функціями 995 | 996 | ```TypeScript 997 | interface Repository { 998 | getAll(): T[]; 999 | getById(id: number): T | null; 1000 | } 1001 | 1002 | class UserRepo implements Repository<{ id: number; name: string }> { 1003 | private users = [{ id: 1, name: "Alice" }]; 1004 | getAll() { return this.users; } 1005 | getById(id: number) { return this.users.find(u => u.id === id) ?? null; } 1006 | } 1007 | ``` 1008 | 1009 | #### Навіщо: 1010 | 1011 | - дозволяють будувати універсальні API (репозиторії, сервіси, колекції); 1012 | 1013 | - зберігають зв’язок між типами в методах/властивостях; 1014 | 1015 | - уникання дублювання коду для різних сутностей. 1016 | 1017 |
1018 | 1019 |
1020 | 30. Як працюють узагальнені (generic) типи у класах TypeScript і як їх застосовувати? 1021 | 1022 | #### TypeScript 1023 | 1024 | У TypeScript можна робити класи параметризованими типами, додаючи параметр `` 1025 | після імені класу. Це дозволяє створювати універсальні класи, які працюють з 1026 | різними типами даних, зберігаючи типобезпеку. 1027 | 1028 | #### Приклад базового generic-класу 1029 | 1030 | ```TypeScript 1031 | class Box { 1032 | constructor(public content: T) {} 1033 | getContent(): T { 1034 | return this.content; 1035 | } 1036 | } 1037 | 1038 | const numberBox = new Box(123); 1039 | const stringBox = new Box("Hello"); 1040 | 1041 | console.log(numberBox.getContent()); // 123 1042 | console.log(stringBox.getContent()); // Hello 1043 | ``` 1044 | 1045 | #### Клас з кількома параметрами типів 1046 | 1047 | ```TypeScript 1048 | class Pair { 1049 | constructor(public key: K, public value: V) {} 1050 | } 1051 | 1052 | const pair = new Pair("id", 42); 1053 | ``` 1054 | 1055 | #### Обмеження generic через extends 1056 | 1057 | ```TypeScript 1058 | class Collection { 1059 | private items: T[] = []; 1060 | add(item: T) { this.items.push(item); } 1061 | getById(id: number): T | undefined { 1062 | return this.items.find(i => i.id === id); 1063 | } 1064 | } 1065 | 1066 | const users = new Collection<{ id: number; name: string }>(); 1067 | users.add({ id: 1, name: "Alice" }); 1068 | ``` 1069 | 1070 | #### Переваги: 1071 | 1072 | - Універсальність класів без втрати типобезпеки. 1073 | 1074 | - Повторне використання логіки для різних типів. 1075 | 1076 | - Зв’язок між методами і властивостями через один параметр типу. 1077 | 1078 |
1079 | 1080 |
1081 | 31. Як реалізувати узагальнене обмеження (generic constraint) у TypeScript і для чого воно потрібне? 1082 | 1083 | #### TypeScript 1084 | 1085 | У TypeScript можна обмежити generic-параметр за допомогою extends, щоб він 1086 | повинен був відповідати певному типу або інтерфейсу. Це дозволяє безпечно 1087 | використовувати властивості або методи об’єкта всередині функції або класу. 1088 | 1089 | #### Приклад із функцією 1090 | 1091 | ```TypeScript 1092 | interface HasLength { 1093 | length: number; 1094 | } 1095 | 1096 | function logLength(item: T): void { 1097 | console.log(item.length); 1098 | } 1099 | 1100 | logLength("Hello"); // ✅ рядок має length 1101 | logLength([1, 2, 3]); // ✅ масив має length 1102 | logLength(42); // ❌ помилка, number не має length 1103 | ``` 1104 | 1105 | #### Приклад із класом 1106 | 1107 | ```TypeScript 1108 | class Collection { 1109 | private items: T[] = []; 1110 | add(item: T) { this.items.push(item); } 1111 | getById(id: number): T | undefined { 1112 | return this.items.find(i => i.id === id); 1113 | } 1114 | } 1115 | 1116 | const users = new Collection<{ id: number; name: string }>(); 1117 | users.add({ id: 1, name: "Alice" }); // ✅ ok 1118 | ``` 1119 | 1120 | #### Переваги: 1121 | 1122 | - Дозволяє використовувати властивості або методи об’єкта без перевірок типу. 1123 | 1124 | - Зберігає універсальність функцій і класів, але обмежує використання тільки 1125 | сумісними типами. 1126 | 1127 |
1128 | 1129 | ### Розширені типи та техніки в TypeScript 1130 | 1131 |
1132 | 32. Що таке дискримінований союз (Discriminated Union) у TypeScript і як він працює? 1133 | 1134 | #### TypeScript 1135 | 1136 | **Discriminated Union** — це патерн, коли `union` типів має спільну 1137 | властивість-дискримінатор (зазвичай літеральний тип), яка дозволяє компілятору 1138 | звузити тип під час перевірок. 1139 | 1140 | #### Приклад: 1141 | 1142 | ```TypeScript 1143 | type Circle = { 1144 | kind: "circle"; 1145 | radius: number; 1146 | }; 1147 | 1148 | type Rectangle = { 1149 | kind: "rectangle"; 1150 | width: number; 1151 | height: number; 1152 | }; 1153 | 1154 | type Shape = Circle | Rectangle; 1155 | 1156 | function area(shape: Shape): number { 1157 | switch (shape.kind) { 1158 | case "circle": 1159 | return Math.PI * shape.radius ** 2; 1160 | case "rectangle": 1161 | return shape.width * shape.height; 1162 | } 1163 | } 1164 | ``` 1165 | 1166 | #### Особливості: 1167 | 1168 | - `kind` (або інша властивість) має літеральне значення, унікальне для кожного 1169 | варіанту. 1170 | 1171 | - Це дозволяє TypeScript робити type narrowing автоматично у `switch` чи `if`. 1172 | 1173 | - Використовується для моделювання станів, подій, результатів API. 1174 | 1175 | Фактично, це спосіб реалізації type-safe "enum-like" варіантів з різними 1176 | структурами даних. 1177 | 1178 |
1179 | 1180 |
1181 | 33. Що таке утилітний тип Readonly у TypeScript і як його оголосити/використати? 1182 | 1183 | #### TypeScript 1184 | 1185 | `Readonly` — це вбудований утилітний тип, який робить усі властивості об’єкта 1186 | тільки для читання (неможливо змінювати після ініціалізації). 1187 | 1188 | #### Приклад використання: 1189 | 1190 | ```TypeScript 1191 | type User = { 1192 | id: number; 1193 | name: string; 1194 | }; 1195 | 1196 | const u: Readonly = { 1197 | id: 1, 1198 | name: "Alice" 1199 | }; 1200 | 1201 | u.name = "Bob"; // ❌ Помилка: властивість доступна тільки для читання 1202 | ``` 1203 | 1204 | #### Як оголошений всередині TS 1205 | 1206 | ```TypeScript 1207 | type Readonly = { 1208 | readonly [P in keyof T]: T[P]; 1209 | }; 1210 | ``` 1211 | 1212 | - Тобто це mapped type, який додає модифікатор readonly до кожної властивості. 1213 | 1214 | Використовується для іммутабельних даних, DTO та запобігання випадковим змінам. 1215 | 1216 |
1217 | 1218 |
1219 | 34. Що таке mapped types у TypeScript і як їх використовувати? 1220 | 1221 | #### TypeScript 1222 | 1223 | **Mapped types** — це спосіб створювати нові типи на основі існуючих, проходячи 1224 | по ключах (`keyof`) та трансформуючи їх. Це використовується для створення 1225 | утилітних типів (`Readonly`, `Partial`, `Pick` тощо). 1226 | 1227 | #### Базовий приклад: 1228 | 1229 | ```TypeScript 1230 | type User = { 1231 | id: number; 1232 | name: string; 1233 | active: boolean; 1234 | }; 1235 | 1236 | // Робимо всі властивості readonly 1237 | type ReadonlyUser = { 1238 | readonly [K in keyof User]: User[K]; 1239 | }; 1240 | ``` 1241 | 1242 | #### Використання з модифікаторами: 1243 | 1244 | - `readonly` / `-readonly` → додає або прибирає "тільки для читання" 1245 | 1246 | - `?` / `-?` → робить поле опціональним або обов’язковим 1247 | 1248 | ```TypeScript 1249 | type PartialUser = { 1250 | [K in keyof User]?: User[K]; 1251 | }; 1252 | ``` 1253 | 1254 | #### Generic-приклад: 1255 | 1256 | ```TypeScript 1257 | type MyMapped = { 1258 | [P in keyof T]: T[P]; 1259 | }; 1260 | 1261 | type Test = MyMapped<{ a: string; b: number }>; 1262 | // { a: string; b: number } 1263 | ``` 1264 | 1265 | #### Реальні приклади (вбудовані утиліти): 1266 | 1267 | - `Readonly` → робить усі властивості readonly 1268 | 1269 | - `Partial` → робить усі властивості опціональними 1270 | 1271 | - `Required` → робить усі властивості обов’язковими 1272 | 1273 | - `Record` → створює об’єкт, де всі ключі мають значення типу T 1274 | 1275 | Mapped types корисні для масових перетворень типів без дублювання коду. 1276 | 1277 |
1278 | 1279 |
1280 | 35. Що таке умовні типи (Conditional Types) у TypeScript і як вони працюють? 1281 | 1282 | #### TypeScript 1283 | 1284 | **Умовні типи** дозволяють описувати залежності між типами за допомогою 1285 | конструкції T extends U ? X : Y. 1286 | 1287 | - Якщо T підтип U, результат буде X. 1288 | 1289 | - Інакше — Y. 1290 | 1291 | #### Базовий приклад: 1292 | 1293 | ```TypeScript 1294 | type IsString = T extends string ? "yes" : "no"; 1295 | 1296 | type A = IsString; // "yes" 1297 | type B = IsString; // "no" 1298 | ``` 1299 | 1300 | #### Використання з узагальненими типами: 1301 | 1302 | ```TypeScript 1303 | type ElementType = T extends (infer U)[] ? U : T; 1304 | 1305 | type A = ElementType; // string 1306 | type B = ElementType; // number 1307 | ``` 1308 | 1309 | #### Застосування у практиці: 1310 | 1311 | ```TypeScript 1312 | type ApiResponse = T extends Error ? { success: false; error: T } 1313 | : { success: true; data: T }; 1314 | 1315 | type R1 = ApiResponse; // { success: true; data: string } 1316 | type R2 = ApiResponse; // { success: false; error: Error } 1317 | ``` 1318 | 1319 | #### Особливості: 1320 | 1321 | - Працюють у поєднанні з generics, union та mapped types. 1322 | 1323 | - Часто використовуються у вбудованих утилітах: 1324 | 1325 | - `Exclude` 1326 | 1327 | - `Extract` 1328 | 1329 | - `NonNullable` 1330 | 1331 | Умовні типи — це основа для гнучкої метапрограмінгової типізації. 1332 | 1333 |
1334 | 1335 |
1336 | 36. Що таке індексні типи (Indexed Access Types) у TypeScript і як працює ключове слово keyof? 1337 | 1338 | #### TypeScript 1339 | 1340 | `keyof` 1341 | 1342 | - keyof створює об’єднання (union) ключів заданого типу. 1343 | 1344 | - Використовується для обмеження значень ключами інтерфейсу/типу. 1345 | 1346 | ```TypeScript 1347 | type User = { id: number; name: string; active: boolean }; 1348 | type UserKeys = keyof User; 1349 | // "id" | "name" | "active" 1350 | ``` 1351 | 1352 | #### Indexed Access Types (T[K]) 1353 | 1354 | - Дозволяють отримати тип значення за конкретним ключем. 1355 | 1356 | ```TypeScript 1357 | type UserIdType = User["id"]; // number 1358 | type UserNameOrActive = User["name" | "active"]; // string | boolean 1359 | ``` 1360 | 1361 | #### Приклад разом 1362 | 1363 | ```TypeScript 1364 | function getValue(obj: T, key: K): T[K] { 1365 | return obj[key]; 1366 | } 1367 | 1368 | const user: User = { id: 1, name: "Alice", active: true }; 1369 | 1370 | let nameValue = getValue(user, "name"); // string 1371 | let activeValue = getValue(user, "active"); // boolean 1372 | ``` 1373 | 1374 | #### Навіщо це потрібно: 1375 | 1376 | - Для generic-утиліт, які працюють із довільними об’єктами. 1377 | 1378 | - Для побудови type-safe доступу до властивостей. 1379 | 1380 | - Основа для утилітних типів (Pick, Omit, Record тощо). 1381 | 1382 |
1383 | 1384 |
1385 | 37. У чому різниця між приведенням типів (type casting) і твердженням типів (type assertion) у TypeScript? 1386 | 1387 | #### TypeScript 1388 | 1389 | 1. **Твердження типів (Type Assertion)** 1390 | 1391 | - Це інструкція для компілятора, що значення має певний тип. 1392 | 1393 | - Не змінює значення у рантаймі. 1394 | 1395 | - Використовується, коли розробник краще знає тип, ніж TypeScript. 1396 | 1397 | ```TypeScript 1398 | let value: unknown = "Hello"; 1399 | let strLength = (value as string).length; // "повір, це string" 1400 | ``` 1401 | 1402 | 2. **Приведення типів (Type Casting, runtime cast)** 1403 | 1404 | - Це перетворення значення в інший тип у рантаймі (наприклад, Number("123") → 1405 | 123). 1406 | 1407 | - Виконується реальною функцією чи оператором у JS. 1408 | 1409 | ```TypeScript 1410 | let str = "123"; 1411 | let num = Number(str); // runtime casting → 123 1412 | ``` 1413 | 1414 | #### Відмінність 1415 | 1416 | - **Type assertion:** впливає тільки на компіляцію, ніяких змін у рантаймі. 1417 | 1418 | - **Type casting:** реально змінює значення під час виконання. 1419 | 1420 | У TypeScript під "casting" часто мають на увазі type assertions, але це не одне 1421 | й те саме. 1422 | 1423 |
1424 | 1425 |
1426 | 38. Що таке утилітні типи Partial, Required, Readonly та Pick у TypeScript і для чого вони потрібні? 1427 | 1428 | #### TypeScript 1429 | 1430 | 1. `Partial` 1431 | 1432 | - Робить усі властивості опціональними. 1433 | 1434 | ```TypeScript 1435 | type User = { id: number; name: string; }; 1436 | type PartialUser = Partial; 1437 | // { id?: number; name?: string } 1438 | ``` 1439 | 1440 | - Використовується для об’єктів оновлення/патчів. 1441 | 1442 | 2. `Required` 1443 | 1444 | - Робить усі властивості обов’язковими (знімає ?). 1445 | 1446 | ```TypeScript 1447 | type UserOptional = { id?: number; name?: string; }; 1448 | type RequiredUser = Required; 1449 | // { id: number; name: string } 1450 | ``` 1451 | 1452 | - Корисно для валидації, коли потрібен повний об’єкт. 1453 | 1454 | 3. `Readonly` 1455 | 1456 | - Робить усі властивості доступними тільки для читання. 1457 | 1458 | ```TypeScript 1459 | type User = { id: number; name: string; }; 1460 | type ReadonlyUser = Readonly; 1461 | 1462 | const u: ReadonlyUser = { id: 1, name: "Alice" }; 1463 | u.name = "Bob"; // ❌ Помилка 1464 | ``` 1465 | 1466 | - Застосовується для іммутабельних даних. 1467 | 1468 | 4. `Pick` 1469 | 1470 | - Вибирає підмножину властивостей з типу T. 1471 | 1472 | ```TypeScript 1473 | type User = { id: number; name: string; active: boolean }; 1474 | type UserPreview = Pick; 1475 | // { id: number; name: string } 1476 | ``` 1477 | 1478 | - Корисно для DTO, селекторів, відображення лише потрібних полів. 1479 | 1480 | Усі вони побудовані на mapped types + keyof. 1481 | 1482 | Найчастіше застосовуються для гнучкої типізації API, DTO, form state, патчів 1483 | даних. 1484 | 1485 |
1486 | 1487 |
1488 | 39. Що таке тип never у TypeScript і в яких випадках він застосовується? 1489 | 1490 | #### TypeScript 1491 | 1492 | `never` 1493 | 1494 | - Це спеціальний тип, який означає значення, що ніколи не існує. 1495 | 1496 | - Використовується там, де функція або вираз не повертає значення взагалі. 1497 | 1498 | #### Основні випадки використання 1499 | 1500 | 1. **Функція, яка ніколи не завершується успішно** 1501 | 1502 | ```TypeScript 1503 | function fail(message: string): never { 1504 | throw new Error(message); 1505 | } 1506 | ``` 1507 | 1508 | 2. **Функція з нескінченним циклом** 1509 | 1510 | ```TypeScript 1511 | function infiniteLoop(): never { 1512 | while (true) {} 1513 | } 1514 | ``` 1515 | 1516 | 3. **Exhaustive checking (перевірка вичерпності union-типів)** 1517 | 1518 | ```TypeScript 1519 | type Shape = { kind: "circle"; radius: number } 1520 | | { kind: "square"; side: number }; 1521 | 1522 | function area(shape: Shape): number { 1523 | switch (shape.kind) { 1524 | case "circle": return Math.PI * shape.radius ** 2; 1525 | case "square": return shape.side ** 2; 1526 | default: 1527 | const _exhaustiveCheck: never = shape; // якщо додати новий варіант → помилка 1528 | return _exhaustiveCheck; 1529 | } 1530 | } 1531 | ``` 1532 | 1533 | #### Ключові моменти 1534 | 1535 | - `never` — підтип будь-якого типу, але жоден тип не є підтипом never (крім 1536 | нього самого). 1537 | 1538 | - Використовується для строгих перевірок типів і ситуацій, де значення бути не 1539 | може. 1540 | 1541 | never корисний у type-safe error handling та для гарантій повного покриття 1542 | union-типів. 1543 | 1544 |
1545 | 1546 | ### Модулі та простори імен у TypeScript 1547 | 1548 |
1549 | 40. Як організувати код за допомогою модулів у TypeScript? 1550 | 1551 | #### TypeScript 1552 | 1553 | **Основи модулів у TypeScript** 1554 | 1555 | - Кожен файл з import або export стає модулем. 1556 | 1557 | - Використовуються ключові слова export та import (як у ES6). 1558 | 1559 | #### Приклад організації 1560 | 1561 | `math.ts` 1562 | 1563 | ```TypeScript 1564 | export function add(a: number, b: number): number { 1565 | return a + b; 1566 | } 1567 | 1568 | export const PI = 3.14; 1569 | ``` 1570 | 1571 | `app.ts` 1572 | 1573 | ```TypeScript 1574 | import { add, PI } from "./math"; 1575 | 1576 | console.log(add(2, 3)); // 5 1577 | console.log(PI); // 3.14 1578 | ``` 1579 | 1580 | #### Експорт за замовчуванням 1581 | 1582 | ```TypeScript 1583 | // logger.ts 1584 | export default function log(msg: string) { 1585 | console.log("LOG:", msg); 1586 | } 1587 | 1588 | // app.ts 1589 | import log from "./logger"; 1590 | log("hello"); 1591 | ``` 1592 | 1593 | #### Перейменування та групування 1594 | 1595 | ```TypeScript 1596 | import * as MathUtils from "./math"; 1597 | console.log(MathUtils.add(1, 2)); 1598 | ``` 1599 | 1600 | #### Організація проекту 1601 | 1602 | - Файлова структура: групувати код за доменами (наприклад, services/, models/, 1603 | utils/). 1604 | 1605 | - Barrel files (індексні модулі): об’єднувати кілька експортувань в одному 1606 | файлі. 1607 | 1608 | ```TypeScript 1609 | // utils/index.ts 1610 | export * from "./math"; 1611 | export * from "./logger"; 1612 | 1613 | // app.ts 1614 | import { add, PI } from "./utils"; 1615 | ``` 1616 | 1617 | #### Конфігурація 1618 | 1619 | - У `tsconfig.json` можна налаштувати: 1620 | 1621 | - "module": (esnext, commonjs, amd, залежно від оточення). 1622 | 1623 | - "baseUrl", "paths": для зручних alias-імпортів. 1624 | 1625 | ```json 1626 | { 1627 | "compilerOptions": { 1628 | "baseUrl": "./src", 1629 | "paths": { 1630 | "@utils/*": ["utils/*"] 1631 | } 1632 | } 1633 | } 1634 | ``` 1635 | 1636 | Модулі в TypeScript = ті самі ES6 модулі, але з повною підтримкою типів. 1637 | 1638 |
1639 | 1640 |
1641 | 41. У яких випадках доцільно використовувати простори імен (namespace) у TypeScript 1642 | 1643 | #### TypeScript 1644 | 1645 | #### Простори імен (namespace) 1646 | 1647 | - Це спосіб групувати логіку всередині одного глобального об’єкта. 1648 | 1649 | - Використовувалися до появи модулів для уникнення колізій у глобальному 1650 | просторі імен. 1651 | 1652 | ```TypeScript 1653 | namespace Utils { 1654 | export function add(a: number, b: number): number { 1655 | return a + b; 1656 | } 1657 | 1658 | export const PI = 3.14; 1659 | } 1660 | 1661 | console.log(Utils.add(2, 3)); 1662 | ``` 1663 | 1664 | #### Коли можна застосовувати 1665 | 1666 | 1. У legacy-проєктах або коли немає системи модулів (наприклад, код вбудовується 1667 | напряму в ` 3617 | 3618 | 3623 | ``` 3624 | 3625 | 3. Типізація пропсів і емісій 3626 | 3627 | ```TypeScript 3628 | 3638 | ``` 3639 | 3640 | 4. Типи для композиційного API 3641 | 3642 | ```TypeScript 3643 | import { Ref } from "vue" 3644 | 3645 | function useCounter(initial: number): { count: Ref, inc: () => void } { 3646 | const count = ref(initial) 3647 | const inc = () => count.value++ 3648 | return { count, inc } 3649 | } 3650 | ``` 3651 | 3652 | 5. Конфігурація `tsconfig.json` 3653 | 3654 | Важливі опції: 3655 | 3656 | ```json 3657 | { 3658 | "compilerOptions": { 3659 | "strict": true, 3660 | "module": "ESNext", 3661 | "target": "ESNext", 3662 | "moduleResolution": "Node", 3663 | "jsx": "preserve", 3664 | "allowJs": false, 3665 | "types": ["vite/client"] 3666 | } 3667 | } 3668 | ``` 3669 | 3670 | 6. Додаткові пакети 3671 | 3672 | - `vue-tsc` — статична перевірка .vue файлів 3673 | 3674 | - `@vue/runtime-core` — типи Vue API 3675 | 3676 | - `volar` (IDE extension) — краща інтеграція TS у Vue 3677 | 3678 | У Vue 2 можна було додавати TypeScript через `vue-class-component`, але зараз 3679 | рекомендується Vue 3 + `