unknown vs any
1. Що робить unknown
unknown- це безпечна альтернативаany. Він каже: "я не знаю, що це за значення, тому ти повинен довести його тип, перш ніж використовувати".
Приклад:
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 | Ні | Так |
| Може призвести до рантайм-помилок | Часто | Тільки якщо обійти перевірки |
Приклад:
let a: any = "hello";
let u: unknown = "hello";
a.foo(); // TS пропустить -> впаде в runtime
u.foo(); // TS не дозволить -> безпечно3. Чому unknown все ще можна використовувати погано
Хоча unknown безпечніший, все залежить від того, що ти з ним робиш.
Якщо ти насильно "ламаєш" типізацію, unknown перестає бути безпечним.
Помилка 1: Примусове приведення через as
let data: unknown = "Hello";
const num = data as number; // примусове приведення
console.log(num.toFixed(2)); // runtime помилкаПриведення (as number) обходить усі перевірки TS.
Тобто - ти знову повернувся до поведінки any.
Висновок:
unknown безпечний, поки ти не змушуєш TS "повірити тобі на слово".
Помилка 2: Широке поширення unknown
Якщо ти повертаєш unknown з функцій або зберігаєш його в структурах даних,
типова система втрачає контекст.
Приклад:
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 більше не знає, що повертає функція.
function getUser(): unknown {
return { name: "Alex", age: 30 };
}
const user = getUser();
user.name; // Помилка - TS не знає, що там об'єктКод безпечний, але марний: TS захищає від помилок, але не допомагає розробляти.
Помилка 4: Присвоєння unknown без уточнення
let data: unknown = 42;
let str: string = data; // Помилка: Type 'unknown' is not assignable to type 'string'Добре, що TypeScript ловить це,
але якщо ти напишеш as string, все одно зламається логіка:
let str = data as string;
console.log(str.toUpperCase()); // runtime помилка4. Як правильно використовувати unknown
Використовуй unknown як бар'єр безпеки -
на межах із зовнішніми даними, де ти не можеш довіряти типам (API, JSON, введення користувача).
Приклад:
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 guardT-> повертаємо типізоване значення
5. Коли unknown кращий за any, а коли - ні
| Ситуація | Краще unknown | Краще any |
|---|---|---|
| При отриманні даних з API | Так | Ні |
| При швидкому дебагу або тимчасовому коді | Можна, але громіздко | Так (тимчасово) |
| При написанні універсальних функцій | Так (звужуй тип пізніше) | Ні |
| У legacy-коді, де немає часу на суворі перевірки | Незручно | Тимчасово допустимо |
| У публічних бібліотеках | Так (зовнішнє введення - unknown) | Ні |
6. Правильний приклад з перевірками
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під маскою.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.