Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «unknown vs any». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`unknown`** - це безпечна альтернатива `any`: він каже «я не знаю, що це за значення, тому ти повинен довести його тип, перш ніж використовувати», і не дозволяє викликати жодні методи без перевірки. **Ключове:** попри це, `unknown` перестає бути безпечним, якщо примусово привести його через `as` або занадто широко розповсюджувати без звуження - у такому разі він фактично перетворюється на `any` під маскою.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що робить `unknown` > `unknown` - це **безпечна альтернатива** `any`. > Він каже: "я не знаю, що це за значення, **тому ти повинен довести його тип, перш ніж використовувати**". Приклад: ```javascript let value: unknown = "hello"; value.toUpperCase(); // Помилка: Object is of type 'unknown' if (typeof value === "string") { value.toUpperCase(); // OK, тип доведено } ``` На відміну від `any`, TypeScript **не дозволяє робити нічого**, поки ти не уточниш (звузиш) тип. Саме це робить `unknown` *безпечним за замовчуванням*. --- ## 2. Чому `unknown` безпечніший, ніж `any` | Поведінка | `any` | `unknown` | |---|---|---| | Можна викликати методи без перевірки | Так | Ні | | Можна присвоювати в інші типи | Без обмежень | Лише після перевірки | | IDE підказує властивості | Ні | Ні (до перевірки) | | Вимагає type narrowing | Ні | Так | | Може призвести до рантайм-помилок | Часто | Тільки якщо обійти перевірки | Приклад: ```javascript let a: any = "hello"; let u: unknown = "hello"; a.foo(); // TS пропустить -> впаде в runtime u.foo(); // TS не дозволить -> безпечно ``` --- ## 3. Чому `unknown` все ще можна використовувати **погано** Хоча `unknown` безпечніший, **все залежить від того, що ти з ним робиш**. Якщо ти **насильно "ламаєш" типізацію**, `unknown` перестає бути безпечним. --- ### Помилка 1: Примусове приведення через `as` ```javascript let data: unknown = "Hello"; const num = data as number; // примусове приведення console.log(num.toFixed(2)); // runtime помилка ``` Приведення (`as number`) обходить усі перевірки TS. Тобто - ти знову **повернувся до поведінки** `any`. **Висновок:** `unknown` безпечний, поки ти не змушуєш TS "повірити тобі на слово". --- ### Помилка 2: Широке поширення `unknown` Якщо ти повертаєш `unknown` з функцій або зберігаєш його в структурах даних, типова система втрачає контекст. Приклад: ```javascript function parseJSON(str: string): unknown { return JSON.parse(str); } const result = parseJSON('{"id":1,"name":"Alex"}'); // result: unknown console.log(result.name); // помилка, поки не перевіриш ``` Це *безпечно*, але **незручно** - ти змушений усюди вручну звужувати типи. Якщо таких значень багато, це призводить до **типового хаосу**. --- ### Помилка 3: Занадто узагальнені типи функцій Якщо в API-функції все оголошено як `unknown`, ти **втрачаєш корисність типізації** - IDE більше не знає, що повертає функція. ```javascript function getUser(): unknown { return { name: "Alex", age: 30 }; } const user = getUser(); user.name; // Помилка - TS не знає, що там об'єкт ``` Код безпечний, але марний: TS захищає від помилок, але не допомагає розробляти. --- ### Помилка 4: Присвоєння `unknown` без уточнення ```javascript let data: unknown = 42; let str: string = data; // Помилка: Type 'unknown' is not assignable to type 'string' ``` Добре, що TypeScript **ловить це**, але якщо ти напишеш `as string`, все одно **зламається логіка**: ```javascript let str = data as string; console.log(str.toUpperCase()); // runtime помилка ``` --- ## 4. Як правильно використовувати `unknown` **Використовуй** `unknown` **як бар'єр безпеки** - на межах із *зовнішніми даними*, де ти не можеш довіряти типам (API, JSON, введення користувача). Приклад: ```javascript function parse<T>(json: string): T { const data: unknown = JSON.parse(json); if (isUser(data)) { return data; // TS тепер впевнений } throw new Error("Invalid user data"); } ``` Тут: - `unknown` -> безпечний старт - `isUser()` -> *type guard* - `T` -> повертаємо типізоване значення --- ## 5. Коли `unknown` кращий за `any`, а коли - ні | Ситуація | Краще `unknown` | Краще `any` | |---|---|---| | При отриманні даних з API | Так | Ні | | При швидкому дебагу або тимчасовому коді | Можна, але громіздко | Так (тимчасово) | | При написанні універсальних функцій | Так (звужуй тип пізніше) | Ні | | У legacy-коді, де немає часу на суворі перевірки | Незручно | Тимчасово допустимо | | У публічних бібліотеках | Так (зовнішнє введення - `unknown`) | Ні | --- ## 6. Правильний приклад з перевірками ```javascript function isUser(value: unknown): value is { id: number; name: string } { return ( typeof value === "object" && value !== null && "id" in value && "name" in value ); } const data: unknown = JSON.parse('{"id":1,"name":"Alex"}'); if (isUser(data)) { console.log(data.name.toUpperCase()); // безпечно } else { console.error("Invalid user"); } ``` Тут `unknown` виконує своє завдання - захищає від невірного типу, поки ти не доведеш протилежне. --- ## 7. Принципова різниця у філософії | | `any` | `unknown` | |---|---|---| | Філософія | "Я знаю, що роблю" | "Я поки не знаю, що це" | | Безпека | відсутня | максимальна | | Застосування | тимчасові рішення, legacy | зовнішні дані, API, динаміка | | Перевірка типів | вимкнена | обов'язкова | | Порушує контракт типів | легко | лише через `as` | --- ## Підсумок | Питання | Відповідь | |---|---| | Чому `unknown` безпечніший? | Він **змушує** тебе перевірити тип перед використанням. | | Чому може бути небезпечним? | Якщо **обійти перевірки** через `as` або використовувати занадто широко, втрачається сенс типізації. | | Де доречний? | На межах застосунку: парсинг JSON, введення користувача, непередбачувані API. | | Головна ідея | `unknown` - це "безпечне невідоме". Ти не можеш використати значення, поки не доведеш, що воно потрібного типу. | --- **Просто запам'ятай:** > `any` - "я знаю краще за TypeScript". > `unknown` - "TypeScript, допоможи мені переконатися". > > Але якщо ти сам "обманеш" компілятор (через `as`), > то `unknown` перестане бути безпечним і стане звичайним `any` під маскою.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.